Using SHBrowseForFolder in .NET






2.21/5 (6 votes)
Using SHBrowseForFolder in .NET
Update
This article is now mostly out of date. The functionality it describes now exists in the .NET class libraries natively (System.Windows.Forms.FolderBrowserDialog
). The solution is still valid for anyone using .NET 1.0, which is likely to be very few people nowadays.
Introduction
There are many projects on The Code Project that try and solve the fact that the .NET class library does not have a folder picker dialog by writing their own version.
Windows already has a perfectly good folder picker, but it's not always obvious how to get access to it. While C++ has the SHBrowseForFolder
function, there is no easy equivalent in .NET.
This short article describes how to gain access to this functionality from C#.
Using the Windows Folder Picker
The first thing to do is to add a reference to the shell32.dll. Select Project->Add Reference... then select Browse. Add the file c:\windows\system32\shell32.dll (or wherever you have Windows installed).
Once you have added that reference, you can use the following code to access the folder picker.
Shell32.Shell picker = new Shell32.ShellClass();
Shell32.Folder folder = picker.BrowseForFolder
((int)this.Handle, "Resource Updater", 0, 0);
if (folder == null)
return; //user hit cancel
Shell32.FolderItem fi = (folder as Shell32.Folder3).Self;
string thePath = fi.Path;
Notes on the Code
If you just want to use the code, then you can ignore this section. Just copy and paste the above into your code and you're set to go.
The BrowseForFolder
method is completely documented in the MSDN.
The call used here creates a default picker rooted at the My Computer location. The two "0"s as the last parameters are options that can modify the picker's behaviour, and are fully detailed in the MSDN entry.
The tricky part of the code is actually getting the path value from the returned object. A Shell Folder object is returned as the result (or null
if the user hits cancel). This folder "object" is actually a COM+ interface pointer to a COM+ object. For simplicity, you can think of this just as a normal object though.
For some reason known only to Microsoft, this object doesn't actually have any direct way of getting the path value. What we need to do instead is gain access to the folder's FolderItem
object, which does store the path. The Folder
object returned is actually a base interface (think of this as a base class) which does not support the method we need. We cast it to the interface we require and can then gain access to the folder item (folder as Shell32.Folder3)
.
Once we have the folder item, we just ask it for the path.
Conclusion
As it turns out, gaining access to a standard folder picker is quite easy, and certainly faster than writing a class that does the same thing.
Hope someone finds this useful.