10

I have an application that makes frequent use of launching explorer.exe. I would like to re-use existing/already-opened explorer windows instead of creating a new one each time I start the process.

Here is what my code looks like:

System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo
{
    UseShellExecute = true,
    FileName = "Explorer.exe",
    Arguments = myDirectoryPath
};
System.Diagnostics.Process.Start(info);

I didn't see a command-line switch to do this. One approach I tried was to simply kill any 1 existing explorer process and replace it with a new one:

var processes = System.Diagnostics.Process.GetProcesses(Environment.MachineName);int kills = 0;
for (int i = 0; i < processes.Length; i++)
{
    System.Diagnostics.Process p = processes[i];
    if (p.ProcessName == "explorer" && kills < 1)
        ++kills
    p.Kill();
}

But this results in the unwanted effect of not just killing 1 process, but killing explorer completely so that even the taskbar disappears.

So, how do you use an existing Explorer window, if one exists, to start Explorer?

4
  • What happens if your user has an explorer window open to a directory for some other reason and doesn't want to be taken out of that directory? Do you think this approach could cause your users to get frustrated?
    – Phil
    Commented Jan 28, 2011 at 17:31
  • That's a valid concern, still, my users said they just said they wanted to re-use any existing explorer windows, instead of having my app open new copies every time. Otherwise, I'd have to determine exactly which explorer windows were opened by my app, and only re-use those.
    – T. Webster
    Commented Jan 28, 2011 at 18:41
  • See also stackoverflow.com/questions/3010305/…
    – rogerdpack
    Commented Sep 23, 2013 at 21:10
  • I implemented this in C# at this answer Commented Nov 27, 2020 at 23:32

4 Answers 4

1

The IShellWindows COM interface will give you a list of open explorer windows, you can get and set the address of any explorer window, see this blog entry for a C++ sample. I doubt .NET has a native implementation of this, so you probably need to PInvoke

2
  • 1
    That may be helpful, I'll take a look, though I was looking for something more along the lines of "here's a code snippet of how to do this..."
    – T. Webster
    Commented Jan 28, 2011 at 23:03
  • so there's really no command line option to re-use previously existing windows? odd...
    – rogerdpack
    Commented Aug 31, 2012 at 18:01
1

http://pinvoke.net/default.aspx/shell32/SHOpenFolderAndSelectItems.html

This works for me

[DllImport("shell32.dll", SetLastError = true)]
public static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, uint dwFlags);

[DllImport("shell32.dll", SetLastError = true)]
public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out] out IntPtr pidl, uint sfgaoIn, [Out] out uint psfgaoOut);

public static void ShowInExplorer(string filePath)
{
    ShowInExplorer(System.IO.Path.GetDirectoryName(filePath), System.IO.Path.GetFileName(filePath));
}
public static void ShowInExplorer(string folderPath, string file)
{
    // god bless you pinvoke.net :)

    IntPtr nativeFolder;
    uint psfgaoOut;
    SHParseDisplayName(folderPath, IntPtr.Zero, out nativeFolder, 0, out psfgaoOut);

    if (nativeFolder == IntPtr.Zero)
    {
        // Log error, can't find folder
        return;
    }

    IntPtr nativeFile;
    SHParseDisplayName(System.IO.Path.Combine(folderPath, file), IntPtr.Zero, out nativeFile, 0, out psfgaoOut);

    IntPtr[] fileArray;
    if (nativeFile == IntPtr.Zero)
    {
        // Open the folder without the file selected if we can't find the file
        fileArray = new IntPtr[] { nativeFolder };
    }
    else
    {
        fileArray = new IntPtr[] { nativeFile };
    }

    SHOpenFolderAndSelectItems(nativeFolder, (uint)fileArray.Length, fileArray, 0);

    Marshal.FreeCoTaskMem(nativeFolder);
    if (nativeFile != IntPtr.Zero)
    {
        Marshal.FreeCoTaskMem(nativeFile);
    }
}
0

Another option would be to (if you don't know the HWND of the explorer window you already opened/want to reuse) enumerate and find the window with a title that "looks like" what you want, then instruct that window to come to the foreground. It wouldn't reveal the exact file you want in it, but it might be simpler than other options :)

0

This is too complicated, so don't do that. Try this instead-

taskkill /f /im explorer.exe`

If you need to start it back up, then, press Ctrl+Shift+Esc, then click File, then Create new task, then type cmd, [make sure Create this task with administrative privileges is checked first!] then click OK or press Enter, then enter the following code-

start explorer.exe

Now explorer.exe must be restarted!

Not the answer you're looking for? Browse other questions tagged or ask your own question.