none
User defined RootFolder for FolderBrowserDialog

    Question

  • Does anyone know of anyway to set the RootFolder on a FolderBrowserDialog to a custom path? In my case, WinXP: "C:\Documents and Settings", Vista+: "C:\Users".

    I've gotten as far as going down to Win API calls, like SHGetFolderLocation() to get the pidl and then pass that into SHBrowseForFolder. This works for Win XP as I can specify CSIDL_Profiles (0x003e) for "C:\Documents and Settings". However, on Vista this does not work because of KnownFolders.

    So, I guess my real question is how can I use KNOWNFOLDERID - FOLDERID_UserProfiles with SHBrowseForFolder?

    What would be better yet, is to figure out how this is working internally. This is what I'm trying to convert to C# .NET.
        Set objShell = CreateObject("Shell.Application")
        Set objFolder = objShell.BrowseForFolder(0, "Select Profile for Current Logon name", 0, "C:\Users")
        // To be able to set a custom root folder ("C:\Users")
    Thursday, December 17, 2009 6:14 PM

Answers

  • Figured it out:

    var folder = shellType.InvokeMember("BrowseForFolder", BindingFlags.InvokeMethod, null, shell, new object[] { 0, "Title", 0, "RootPath" });
    if (folder == null) return; // User clicked cancel
    var title = folder.GetType().InvokeMember("Title", BindingFlags.GetProperty, null, folder, null);
    • Marked as answer by ParkerJay86 Thursday, December 17, 2009 8:45 PM
    Thursday, December 17, 2009 8:11 PM

All replies

  • Hi,

    Could you try this code.

                FolderBrowserDialog fbd = new FolderBrowserDialog();
                string directoryName = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                directoryName = System.IO.Path.GetDirectoryName(directoryName);
                directoryName = System.IO.Path.GetDirectoryName(directoryName);
                fbd.SelectedPath = directoryName;
    
                fbd.ShowDialog();
    Thursday, December 17, 2009 6:55 PM
  • I don't want the user to be able to navigate "up" or somewhere else though. That's why I want the dialog to be rooted at "C:\Documents and Settings\" or "C:\Users\".
    Thursday, December 17, 2009 7:29 PM
  • Use the DirList and FileList boxes.  They give you more control.  Or, roll your own.
    Thursday, December 17, 2009 7:48 PM
  • OK, I've gotten a little closer.

    var shellType = Type.GetTypeFromProgID("Shell.Application");
    var shell = Activator.CreateInstance(shellType);
    var result = shellType.InvokeMember("BrowseForFolder", BindingFlags.InvokeMethod, null, shell, new object[] { 0, "Title", 0, "C:\Users" });
    if(result == null) return;

    But, now I can't figure out how to pull the Title off of the Folder object "result".
    http://msdn.microsoft.com/en-us/library/bb787868(VS.85).aspx

    Any ideas?
    Thursday, December 17, 2009 8:00 PM
  • Figured it out:

    var folder = shellType.InvokeMember("BrowseForFolder", BindingFlags.InvokeMethod, null, shell, new object[] { 0, "Title", 0, "RootPath" });
    if (folder == null) return; // User clicked cancel
    var title = folder.GetType().InvokeMember("Title", BindingFlags.GetProperty, null, folder, null);
    • Marked as answer by ParkerJay86 Thursday, December 17, 2009 8:45 PM
    Thursday, December 17, 2009 8:11 PM
  • Thanks to ParkerJay for this answer, which got me 80% of the way there.

    I wrapped this up into the following function, which returns the full path to the selected folder. What I can't see how to do is set not just the root of the folder that you browse within, but also the initially selected folder. That is, this works to set the equivalent of FolderBrowserDialog.RootFolder, but not FolderBrowserDialog.SelectedPath. Any ideas?


    using
    System;
    using System.Reflection;

    /// <summary>
    /// Invokes the system BrowseToFolder, but allowing a user-specified root path
    /// </summary>
    /// <param name="title">The title for the dialog</param>
    /// <param name="rootPath">The root path where browsing starts</param>
    /// <returns>The user-selected path if the user pressed OK, or null if the user cancelled</returns>

     

     

    public string BrowseToFolder(string title, string rootPath)
    {
       var shellType = Type.GetTypeFromProgID("Shell.Application");
       var shell = Activator.CreateInstance(shellType);
       var folder = shellType.InvokeMember("BrowseForFolder",
       BindingFlags.InvokeMethod, null, shell, new object[] { 0, title, 0, rootPath });
       if (folder == null) return null; // User clicked cancel
       var folderSelf = folder.GetType().InvokeMember("Self", BindingFlags.GetProperty, null, folder, null);
       return folderSelf.GetType().InvokeMember("Path", BindingFlags.GetProperty, null, folderSelf, null) as string;
    }
    Sunday, March 14, 2010 7:38 PM