Search code examples
c#winapiregistrywindows-explorersingle-instance

IExplorerBrowser - Browse in place without starting default application


I am developing windows file manager application, essentialy it wraps IExplorerBrowser giving me exact controls as you would have in your Windows explorer.

I've implemented single instance using Mutex and IPC for passing arguments.

So now I wanted to be able to register my file manager as default application when you open directory from ie. desktop

So I created registry script like this:

REGEDIT4

[HKEY_CURRENT_USER\Software\Classes\Drive\shell]
@="AppName"

[HKEY_CURRENT_USER\Software\Classes\Drive\shell\AppName]
@="Open in AppName"

[HKEY_CURRENT_USER\Software\Classes\Drive\shell\AppName\command]
@="\"<app-path>\" %1"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell]
@="AppName"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\AppName]
@="Open in AppName"

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\AppName\command]
@="\"<app-path>\" \"%1\""

It works as expected, if I double click directory it starts my app, and since I implemented single instance it doesn't spawn more than one instance.

Since I have tabbed interface in my app, every time you open directory it creates new tab with IExplorerBrowser control.

The problem is, now the IExplorerBrowser control behaviour has changed, when I open directory from control I get new tab instead of navigating inside control, which is logical (It always calls registry command for starting my app with direcotry as arg)

TL; DR;

How does windows explorer handle this? How does windows explorer know if directory was opened from ie. desktop, or from inside Windows explorer so that it navigates inside "listview" instead of opening new window?


Solution

  • It has to be a better way to do this, but this works:

      HResult ICommDlgBrowser3.OnDefaultCommand(IntPtr ppshv)
        {
            if (SelectedItems.Count > 0)
            {
                var item = SelectedItems[0];
    
                ShellNativeMethods.ShellFileGetAttributesOptions sfgao;
                item.NativeShellItem2.GetAttributes(ShellNativeMethods.ShellFileGetAttributesOptions.Folder, out sfgao);
                bool isFolder = (sfgao & ShellNativeMethods.ShellFileGetAttributesOptions.Folder) != 0;
    
                if (isFolder)
                {
                    Navigate(SelectedItems[0]);
                    return HResult.Ok;
                }
            }
            return HResult.False;
        }