3

I am using the following code so that when the user clicks on a button, an instance of Windows Explorer is opened at a specific path. But this causes a new instance of the Explorer to be opened.

I want to change it so that, if Explorer is already open in the same path, the program does not create a new process and instead bring the open instance to front.

private void button_Click(object sender, EventArgs e) { if (Directory.Exists(myPath)) Process filesFolder = Process.Start("explorer.exe", Conf.FilesLocation); } 
3
  • Then don't start a new instance, find the existing one's window and bring it to the foreground Commented Nov 20, 2015 at 12:36
  • 1
    @PanagiotisKanavos That's the question. How do I know if it's already open or not? Commented Nov 20, 2015 at 12:49
  • @disasterkid, see my answer to know if it's already open or not. Commented Nov 26, 2020 at 4:51

5 Answers 5

6

You can use the "open" verb, which will open directories in explorer and re-use an an existing explorer.exe if you pass it a directory that it already has open: So, assuming Conf.FilesLocation is a directory:

 var proc = new ProcessStartInfo(); proc.FileName = Conf.FilesLocation; proc.Verb = "open"; proc.WindowStyle = ProcessWindowStyle.Hidden; Process.Start(proc ); 
Sign up to request clarification or add additional context in comments.

1 Comment

The line with proc.WindowStyle = ProcessWindowStyle.Hidden; causes this to fail opening explorer.exe, must be removed.
3

What I have found to work as well, is to use the file:// protocol, when you do this Windows seems to give focus to the folder if it is already open, rather than opening another window

Process.Start("file://" + Conf.FilesLocation); 

Comments

3

For me, none of the solutions here work in Win10. For Marcelo's solution exShell.Windows() is always empty, Josh's solution doesn't work for directories, you'll get file does not exist error, and nos' solution throws access denied error.

So here's my working solution:

 [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr Hwnd); [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); public static void ShowInExplorer(string filePath) { IntPtr hWnd = FindWindow("CabinetWClass", Path.GetDirectoryName(filePath)); if(hWnd != IntPtr.Zero) { SetForegroundWindow(hWnd); } else { Process.Start("explorer.exe", Path.GetDirectoryName(filePath)); } } 

Windows Explorer has window class CabinetWClass and sets title to the browsed directory.

So the above code checks to see if an explorer window with a specific directory exists.

If it does exist, the window is brought to the front, otherwise a new instance of explorer is started with the specified directory. Do note that you need to specifically start explorer.exe with the path given as argument, otherwise it'll throw access denied error.

1 Comment

This solution worked wonder for me. Also, I don't know to which extend, but there could be another type of window class name Explorer­WClass according to this blog post, but that is just for old windows versions: devblogs.microsoft.com/oldnewthing/20150619-00/?p=45341 Still this is the most simple working solution I found
2

Although @nos's answer works well, mostly (sometimes, in a not deterministically way it creates another explorer windows even though it may already exists), I became unsatisfied with the time spent by the Process.Start(proc) to open an existing window, sometimes 2 to 4 seconds.

So, adapting some VB.NET code I achieve a very fast way of reusing a existing explorer window that is pointing to a desired folder:

First, add COM references:

using Shell32;//Shell32.dll for ShellFolderView

using SHDocVw;//Microsoft Internet Controls for IShellWindows

 [DllImport("user32.dll")] public static extern int ShowWindow(IntPtr Hwnd, int iCmdShow); [DllImport("user32.dll")] public static extern bool IsIconic(IntPtr Hwnd); public static bool ShowInExplorer(string folderName) { var SW_RESTORE = 9; var exShell = (IShellDispatch2)Activator.CreateInstance( Type.GetTypeFromProgID("Shell.Application")); foreach (ShellBrowserWindow w in (IShellWindows) exShell.Windows()) { if (w.Document is ShellFolderView) { var expPath = w.Document.FocusedItem.Path; if (!Directory.Exists(Path.GetDirectoryName(expPath)) || Path.GetDirectoryName(expPath) != folderName) continue; if (IsIconic(new IntPtr(w.HWND))) { w.Visible = false; w.Visible = true; ShowWindow(new IntPtr(w.HWND),SW_RESTORE); break; } else { w.Visible = false; w.Visible = true; break; } } } } 

Although we are interested in ShellFolderView objects, and foreach (ShellBrowserWindow w in (ShellFolderView) exShell.Windows()) was more logical, unfortunately ShellFolderView does not implement IEnumerable, so, no foreach :(

Anyway, these is a very fast (200 ms) way of select and blink the correct already opened explorer window.

Comments

0

This function uses ShellExecute. If the provided path is already an open Explorer window, that window will un-minimize and come to the front. Otherwise, it opens a new Explorer window.

static void bringWindowToFront(string path) { Process.Start(new ProcessStartInfo { FileName = path, UseShellExecute = true, Verb = "open" }); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.