Home > .NET Code Samples > Code Sample: Navigating special folders with the .NET WebBrowser control

Code Sample: Navigating special folders with the .NET WebBrowser control

March 23rd, 2008

With the .NET Framework 2.0, Microsoft introduced the WebBrowser control, a managed code wrapper for the WebBrowser ActiveX control. Unfortunately, compared to the ActiveX version, the .NET version of the control lacks some functionality. You can navigate websites, local HTML documents and folder locations using respective protocol handler prefixes (“http://”, “file://”). What you cannot do with the .NET WebBrowser control is navigate special folders like “My Computer” or the control panel, as these folders are not identified by a path but by CSIDLs. So my goal was to extend the existing WebBrowser class to provide this ability.

First of all I did some research on the topic and found a Knowledge Base article describing the necessary steps to navigate a PIDL (pointer to an ITEMIDLIST) with the ActiveX version of the WebBrowser control. So all I had to do was convert the code sample to C#.

Here’s my resulting Navigate2CSIDL method:

public void Navigate2CSIDL(ShellEnums.CSIDLValues csidl) {

    const int S_OK = 0;

    IntPtr pidl = IntPtr.Zero;

    if (SHGetSpecialFolderLocation(IntPtr.Zero, (int)csidl, ref pidl) == S_OK) {
        uint cbpidl = LocalSize(pidl);
        if (cbpidl > 0) {
            byte[] abpidl = new byte[cbpidl];
            Marshal.Copy(pidl, abpidl, 0, ((int)cbpidl - 1));
            object location = (object)abpidl;
            Marshal.FreeCoTaskMem(pidl);

            try {
                object nil = Type.Missing;
                ((SHDocVw.WebBrowser)base.ActiveXInstance).Navigate2 (
                  ref location, ref nil, ref nil, ref nil, ref nil);
            }
            catch (COMException exception) {
                if (exception.ErrorCode != -2147023673
                    /*Operation was canceled by the user*/) {
                    throw;
                }
            }
        }
    }
    else {
        throw new ArgumentOutOfRangeException();
    }
}

The method takes only one parameter: the CSIDL of the special folder to navigate to. First of all, I use SHGetSpecialFolderLocation() to obtain the PIDL of the desired special folder. Since the Navigate2() method of the ActiveX WebBrowser control takes the PIDL wrapped in a SAFEARRAY, we can copy the PIDL to a byte array. Next we call Navigate2() to navigate the WebBrowser control to the folder. ComInterop handles the marshalling of the byte array to a SAFEARRAY for us. And that’s all we have to do.

To be able to conveniently use this funcionality, I created a new class (“WebBrowserExt”) which inherits from System.Windows.Forms.WebBrowser. As the control consumer might want to interact with the special folder, I added two properties (FolderView and Folder) in analogy to the Document property of the WebBrowser control class:

/// 
/// Returns the shell folder object displayed in the webbrowser control.
/// 
public Shell32.Folder2 Folder {
    get {
        IShellFolderViewDual2 folderview = this.FolderView;
        if (folderview != null) {
            return folderview.Folder as Folder2;
        }
        else {
            return null;
        }
    }
}

/// 
/// Returns the shell folderview object displayed in the webbrowser control.
/// 
public Shell32.IShellFolderViewDual2 FolderView {
    get {
        return ((SHDocVw.WebBrowser)base.ActiveXInstance).Document
                 as IShellFolderViewDual2;
    }
}

See the documentation of IShellFolderViewDual2 and Folder2 to find out what you can do with these. These interfaces are supplied by adding references to ShDocVw.dll and Shell32.dll to the project. I put together a small sample project to demonstrate the capabilities of my WebBrowserExt control. This is a Visual Studio 2008 project, so you need at least the free Visual C# 2008 Express Edition to open it.

Here’s a screenshot of the sample project showing the control panel:

Webbrowser_control

Download the sample project here. I also posted this on Channel9.

Categories: .NET Code Samples
  1. gilvini
    March 17th, 2009 at 12:01 | #1

    Hi,

    Excellent! Exactly what I was looking for.
    Can you please specify how to implement “Up” button (navigating to parent folder)?

    Thanks,
    gilvini

  2. no1
    September 2nd, 2010 at 00:33 | #2

    Hey I’m trying to get this to work. I downloaded and built the sample yet I get this error message when I click the Open Control Panel button:

    System.ArgumentException: Value does not fall within the expected range.
    at SHDocVw.IWebBrowser2.Navigate2(Object& URL, Object& Flags, Object& TargetFrameName, Object& PostData, Object& Headers)
    at WebBrowserExtSample.WebBrowserExt.Navigate2CSIDL(CSIDLValues csidl)
    at WebBrowserExtSample.frmMain.btnNavigate_Click(Object sender, EventArgs e)

    I also kept getting this same message in my own testing. Is this possibly an IE8 bug?

  3. no1
    September 2nd, 2010 at 00:53 | #3

    @no1
    Sorry for the double post but just giving an update, I tried this on the same machine after I uninstalled IE8 (thus reverting back to IE7) and the code works as expected.

  4. September 2nd, 2010 at 09:11 | #4

    @no1
    Unfortunately, this sample won’t work anymore when Internet Explorer 8 is installed. I had a hard time finding a workaround. You still can use the WebBrowser control to show the contents of shell special folders, however it’s no longer possible to use all CSIDLs. To navigate the control panel, you can use this navigation target instead “shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}” (without the quotes).

    The reason behind this is detailed here: http://blogs.msdn.com/b/ieinternals/archive/2009/12/30/windows-7-web-browser-control-will-not-browse-file-system.aspx

    You can find a comprehensive list of shell special folder GUIDs in Ed Bott’s ZDNET posting on the Windows “God Mode” here: http://www.zdnet.com/blog/bott/the-ultimate-god-mode-list-39-secret-windows-7-shortcuts/1615

    Hope this helps.

Comments are closed.