If Windows explorer is open at a specific path, do not create a new instance

断了今生、忘了曾经 提交于 2021-02-16 21:29:47

问题


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);               
}

回答1:


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 );



回答2:


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);



回答3:


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.



来源:https://stackoverflow.com/questions/33826845/if-windows-explorer-is-open-at-a-specific-path-do-not-create-a-new-instance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!