SHBrowseForFolder (shell32)
Last changed: -71.212.36.53

.
Summary

C# Signature:

[DllImport("shell32.dll")]
static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);

User-Defined Types:

BROWSEINFO

Notes:

None.

Tips & Tricks:

Please add some!

Sample Code:

    public class BrowseForFolder
    {
        // Browsing for directory.
        private uint BIF_RETURNONLYFSDIRS   = 0x0001;  // For finding a folder to start document searching
        private uint BIF_DONTGOBELOWDOMAIN  = 0x0002;  // For starting the Find Computer
        private uint BIF_STATUSTEXT     = 0x0004;  // Top of the dialog has 2 lines of text for BROWSEINFO.lpszTitle and one line if
        // this flag is set.  Passing the message BFFM_SETSTATUSTEXTA to the hwnd can set the
        // rest of the text.  This is not used with BIF_USENEWUI and BROWSEINFO.lpszTitle gets
        // all three lines of text.
        private uint BIF_RETURNFSANCESTORS  = 0x0008;
        private uint BIF_EDITBOX        = 0x0010;   // Add an editbox to the dialog
        private uint BIF_VALIDATE       = 0x0020;   // insist on valid result (or CANCEL)

        private uint BIF_NEWDIALOGSTYLE     = 0x0040;   // Use the new dialog layout with the ability to resize
        // Caller needs to call OleInitialize() before using this API
        private uint BIF_USENEWUI  = 0x0040 + 0x0010; //(BIF_NEWDIALOGSTYLE | BIF_EDITBOX);

        private uint BIF_BROWSEINCLUDEURLS  = 0x0080;   // Allow URLs to be displayed or entered. (Requires BIF_USENEWUI)
        private uint BIF_UAHINT         = 0x0100;   // Add a UA hint to the dialog, in place of the edit box. May not be combined with BIF_EDITBOX
        private uint BIF_NONEWFOLDERBUTTON  = 0x0200;   // Do not add the "New Folder" button to the dialog.  Only applicable with BIF_NEWDIALOGSTYLE.
        private uint BIF_NOTRANSLATETARGETS = 0x0400;  // don't traverse target as shortcut

        private uint BIF_BROWSEFORCOMPUTER  = 0x1000;  // Browsing for Computers.
        private uint BIF_BROWSEFORPRINTER   = 0x2000;// Browsing for Printers
        private uint BIF_BROWSEINCLUDEFILES = 0x4000; // Browsing for Everything
        private uint BIF_SHAREABLE      = 0x8000;  // sharable resources displayed (remote shares, requires BIF_USENEWUI)

        [DllImport("shell32.dll")]
        static extern IntPtr SHBrowseForFolder(ref BROWSEINFO lpbi);

          // Note that the BROWSEINFO object's pszDisplayName only gives you the name of the folder.
        // To get the actual path, you need to parse the returned PIDL
        [DllImport("shell32.dll", CharSet=CharSet.Unicode)]
        static extern uint SHGetPathFromIDList(IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath);

        public delegate int BrowseCallBackProc(IntPtr hwnd, int msg, IntPtr lp, IntPtr wp);
        struct BROWSEINFO
        {
            public IntPtr hwndOwner;
            public IntPtr pidlRoot;
            public string pszDisplayName;
            public string lpszTitle;
            public uint ulFlags;
            public BrowseCallBackProc lpfn;
            public IntPtr lParam;
            public int iImage;
        }
        public int OnBrowseEvent(IntPtr hwnd, int msg, IntPtr lp, IntPtr wp)
        {
            //...
            return 1;
        }

        public string SelectFolder(string caption, string initialPath, Form parent)
        {
            StringBuilder sb = new StringBuilder(256);
            BrowseCallBackProc bc = new BrowseCallBackProc(OnBrowseEvent);
            IntPtr pidl = IntPtr.Zero;
            BROWSEINFO bi;
            bi.hwndOwner = parent.Handle;
            bi.pidlRoot = IntPtr.Zero;
            bi.pszDisplayName = initialPath;
            bi.lpszTitle = caption;
            bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_SHAREABLE;
            //bi.lpfn = bc;
            bi.lpfn = null;
            bi.lParam = IntPtr.Zero;
            bi.iImage = 0;

            try
            {
                pidl = SHBrowseForFolder(ref bi);
                if (0 == SHGetPathFromIDList(pidl, sb))
                {
                    return null;
                }
            }
            finally
            {
                // Caller is responsible for freeing this memory.
                Marshal.FreeCoTaskMem(pidl);
            }

            return sb.ToString();
        }
    }

Alternative Managed API:

If using .net version 1.1 or greater, you can use System.Windows.Forms.FolderBrowserDialog instead -- as long as you are only browsing for folders! If you want to browse for computers or printers, the .Net version does not seem to support this.

Documentation