For enabling my installer's users to conveniently select the service's output folder, I tried to add an OpenFileDialog button to my customized WixCLRDialog class via WinForms designer.
Unfortunately, no dialog opens, the form just freezes. Is this _per design_ (maybe due to a limitation of the used technologies), a bug or is it just me who broke something by doing it wrong?
Currently used code:
private void btnOutputPath_Click(object sender, EventArgs eventArgs)
{
var outputFolder = new OpenFileDialog
{
CheckFileExists = false,
CheckPathExists = true,
FileName = string.Empty,
Filter = string.Empty,
InitialDirectory = txtOutputPath.Text
};
MessageBox.Show("Debug"); // Shows.
outputFolder.ShowDialog(this); // Never opens the dialog, seems to freeze the form.
MessageBox.Show(outputFolder.FileName); // Is never shown.
}
Commenting (read: removing) the object initializer's properties doesn't change anything.
You cannot do this as OpenFileDialog is an ActiveX control and it cannot be used from the thread that is not initialized for hosting COM objects (e.g. [STAThread]). I guess MSI didn't initialized the UI thered correctly. :(
Below is the work around:
```C#
void button1_Click(object sender, EventArgs e)
{
ShowOpenFolder();
}
void ShowOpenFolder()
{
var t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
public static void ThreadProc()
{
var outputFolder = new OpenFileDialog
{
CheckFileExists = false,
CheckPathExists = true
};
outputFolder.ShowDialog();
}
```
@oleg-shilo, thanks for the perfect workaround and the informative explanation. 馃憤
And of course if you want it to be more elegant then:
C#
string SelectFolder()
{
string result = null;
var t = new Thread(()=>
{
using (var dialog = new OpenFileDialog())
{
dialog.CheckFileExists = false;
dialog.CheckPathExists = true;
if (dialog.ShowDialog() == DialogResult.OK)
result = dialog.FileName;
};
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
return result;
}
@oleg-shilo, once again: thanks a lot! :)