|
Hi All,
I am using Microsoft Visual Studio .Net 2003.
I'm experiencing some problems using FolderBrowserDialog control in a Form run by an Installer class during the Setup process of an application.
I have to ask the user to choose a folder for a one specified file during the Setup process.
When I try to Browse for Folders, I get a Window showing only OK and Cancel buttons, the description and nothing more (the treeview does not appear)
Any other solution to use Folder Browser Dialog?
Thanks in Advance
|
| anemvr Monday, May 16, 2005 5:58 AM |
Okay, after much testing I couldn't get it to work either, however I came up with the following:
| | public override void Install(System.Collections.IDictionary stateSaver) { Thread thread = new Thread(new ThreadStart(DoWork)); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); } private void DoWork() { using (System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog()) { dialog.ShowDialog(); } } |
Basically what we are doing is starting a new thread, setting it to use STA and then displaying the dialog from there. This should get you started, but remember to make your code thread safe. Note: If you try to show a FolderBrowserDialog on a thread that is not STA in Visual Studio 2005, an exception is now thrown, so it won't display at all. |
| David M. Kean Monday, May 16, 2005 3:40 PM |
This is typically because the STAThread attribute is missing on your Main. However, because you are using a custom action, try adding to the method that displays the FolderBrowserDialog, like so: | | [STAThread] private void ShowFolderBrowser() { using (FolderBrowserDialog dialog = new FolderBrowserDialog)) { dialog.ShowDialog(); } } |
|
| David M. Kean Monday, May 16, 2005 10:07 AM |
Hi David M. Kean,
Thanks for your help.
I have tried with above code. Still I am not able to see the treeview in FolderBrowserDialog.
Is there any other solution, through which I can achieve my requirement (treeview has to be appeared).
Thanks for any help.
|
| anemvr Monday, May 16, 2005 1:50 PM |
Okay, after much testing I couldn't get it to work either, however I came up with the following:
| | public override void Install(System.Collections.IDictionary stateSaver) { Thread thread = new Thread(new ThreadStart(DoWork)); thread.SetApartmentState(ApartmentState.STA); thread.Start(); thread.Join(); } private void DoWork() { using (System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog()) { dialog.ShowDialog(); } } |
Basically what we are doing is starting a new thread, setting it to use STA and then displaying the dialog from there. This should get you started, but remember to make your code thread safe. Note: If you try to show a FolderBrowserDialog on a thread that is not STA in Visual Studio 2005, an exception is now thrown, so it won't display at all. |
| David M. Kean Monday, May 16, 2005 3:40 PM |
Hi David M. Kean, Thank you for your help. I have incorporated the above code in my setup code. Now FolderBrowserDialog is working good in my setup project. I am able to see the Treeview now. Onec again Thanks for your timely help. |
| anemvr Tuesday, May 17, 2005 11:30 AM |
From Visual C# Express MSDN: ======= " New threads are initialized as ApartmentState.MTA
if their apartment state has not been set before they are started. Apartment
state must be set before a thread is started.
| Note
|
|
The main application thread is initialized to ApartmentState.MTA by
default. The only way to set the apartment state of the main application thread
to ApartmentState.STA
is to apply the STAThreadAttribute
attribute to the entry point method. |
The SetApartmentState method, along with the GetApartmentState
method and the TrySetApartmentState
method, replaces the ApartmentState
property. " =====
So, I did set the atribute for the Main function like this: [STAThread] public static void Main(){...} and it worked ok with the FolderBrowserDialog, without the need to create a special thread just for displaing the dialog.
But setting this atribute for the Main function will affect in any way the capacity of my app to work with multiple threads? I did some test and it seems to work ok with multiple test, but I don't consider myself a expert in this field.. I wood apreciate a more adviced voice
Thank You
|
| IrimiaBC Tuesday, April 18, 2006 1:37 AM |
It doesnt work to me. Could you help me? I dont think that creating a new thread is the solution. I´m trying to set <StaThread()> in the main of the installer class. I cant understand why it doesnt works.
Any help would be appreciated. |
| jorge1234567 Wednesday, June 14, 2006 11:01 AM |
You can't change the ApartmentState of an installer thread, hence why you have to create another thread. Why doesn't it work for you? |
| David M. Kean Wednesday, June 14, 2006 2:05 PM |
I'm glad I checked before posting this same problem. Thanks to David for the answer. Would anyone like to tell me why it works this way? Any one find a KB article on this?
Meanwhile, to do who are like me arrive at this problem via C# and VSS 2005 (BTW, the wrong thread state did not throw an exception for me), here is the C# code that works for me. Note that "myFolderDialog" is my name for the FolderDialog on my form.
public string getFilePath(string dialogString) { try { string pathname = null; Thread FolderDlgThread = new Thread(getFilePathThread); FolderDlgThread.SetApartmentState(ApartmentState.STA); FolderDlgThread.Start(); FolderDlgThread.Join(); pathname = myFolderDialog.SelectedPath; return pathname; } catch (Exception err) { displayException(err); return null; } }
[ STAThread] public void getFilePathThread() { try { string pathname = null; myFolderDialog.Site = null; DialogResult stat = myFolderDialog.ShowDialog(); if (stat == DialogResult.OK) { pathname = myFolderDialog.SelectedPath; } } catch (Exception err) { displayException(err); } } |
| PaulSQL Tuesday, October 31, 2006 4:10 AM |
I have been developing an SSIS package and encountered this issue. The BrowseFolderDialog is blank. It appears as a form, but without a treeview in it. The C# code above worked when nothing else would. Here it is in VB.NET specialized for SSIS:
Code Snippet
Public Sub Main()
Dim thread As New Threading.Thread(New Threading.ThreadStart(AddressOf DoWork))
thread.SetApartmentState(Threading.ApartmentState.STA)
thread.Start()
thread.Join()
Dts.TaskResult = Dts.Results.Success
End Sub
Private Sub DoWork()
Dim fn As String
Dim sfd As New System.Windows.Forms.FolderBrowserDialog
sfd.RootFolder = Environment.SpecialFolder.Desktop'use this for special folders, or set the selected path text for normal or even UNC start paths
sfd.Description = "Drop CSV Files Where?"'The folder browser dialog's caption
If sfd.ShowDialog = Windows.Forms.DialogResult.OK Then fn = sfd.SelectedPath Else Dts.TaskResult = Dts.Results.Failure 'SSIS stuff
Dts.Variables( "varDestFolder").Value = fn 'SSIS stuff
End Sub
|
| UsarianMSkiff Wednesday, June 18, 2008 9:06 PM |
The reason this will always be unpredictable is that you're running on a msiexec.exe process with a restricted set of rights in a threading environment where Windows Installer does not expect you to be showing UI. You're supposed to collect user data up front in the UI sequence and set properties that are used during the actual install (while progress is showing).Your custom actions run too late tochange installationfolders, so effectively all you're doing is application configuration. You should be doing this with a configuration app that runs after the install, and you should just choose a reasonable default folder at install time. The interesting question is from a user that says "but I want to use a different folder now because the folder I used at install time doesn't exist any more. What do I do? Reinstall the darn app again?".
|
| PhilWilson Wednesday, June 18, 2008 9:31 PM |
Just for sharing ^^
Don't use Thread.Join() here, otherwise you will be facing UI of main form gets stuck.
I use Control.Invoke to set the text box on main form, and bind it to the backend member variable.
Code Snippet
public class Utility { static Utility() { _folderBrowserDialog = new FolderBrowserDialog(); _folderBrowserDialog.ShowNewFolderButton = false; _folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyComputer;
_mydelegate = new SetControlValueDelegate(SetControlValue); }
public static void GetFilePath(Control ctrl) {
Thread folderDlgThread = new Thread(new ParameterizedThreadStart(doWork));
folderDlgThread.SetApartmentState(ApartmentState.STA); folderDlgThread.Start(ctrl);
}
[STAThread] private static void doWork(object data) { lock (_thisLock) { if (_folderBrowserDialog.ShowDialog() == DialogResult.OK) { _folderPath = _folderBrowserDialog.SelectedPath;
Control ctrl = (Control)data; if (ctrl.InvokeRequired) { ctrl.Invoke(_mydelegate, new object[] { data, _folderPath }); } } else _folderPath = string.Empty; } }
public delegate void SetControlValueDelegate(Control ctrl, string value);
private static SetControlValueDelegate _mydelegate;
private static void SetControlValue(Control ctrl, string value) { TextBox temp = ctrl as TextBox; if (temp != null) { temp.Text = value;
} }
private static FolderBrowserDialog _folderBrowserDialog; private static string _folderPath;
private static Object _thisLock = new Object(); #endregion }
Austin |
| 天鎖斬月 Monday, July 21, 2008 2:12 AM |
I have implemented the above code butthe FolderBrowserDialog is appearing belowthe actual form! Please Help. |
| Rupi.k Wednesday, April 29, 2009 3:24 PM |