如果Windows资源管理器在特定路径上打开,请不要创建新实例

时间:2015-11-20 12:32:04

标签: c# process windows-explorer

我使用以下代码,以便当用户单击某个按钮时,会在特定路径中打开 Windows资源管理器的实例。但这会导致打开 Explorer 的新实例。

我想更改它,以便如果 Explorer 已在同一路径中打开,程序不会创建新进程,而是将打开的实例放在前面。

private void button_Click(object sender, EventArgs e)
{
    if (Directory.Exists(myPath))
        Process filesFolder =  Process.Start("explorer.exe", Conf.FilesLocation);               
}

4 个答案:

答案 0 :(得分:3)

您可以使用"打开"动词,它将打开资源管理器中的目录并重新使用现有的explorer.exe,如果你传递它已经打开的目录: 因此,假设 var proc = new ProcessStartInfo(); proc.FileName = Conf.FilesLocation; proc.Verb = "open"; proc.WindowStyle = ProcessWindowStyle.Hidden; Process.Start(proc ); 是一个目录:

\u2013

答案 1 :(得分:1)

尽管@nos的答案很有效,但大多数情况下(有时,它可能会以不确定的方式创建另一个资源管理器窗口,即使它可能已经存在),但我对Process.Start(proc)所花费的时间却不满意窗口,有时需要2到4秒。

因此,调整一些VB.NET code可以实现重用现有资源管理器窗口的快速方法,该窗口指向所需文件夹:

首先,添加COM引用:

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

尽管我们对ShellFolderView对象感兴趣,并且foreach (ShellBrowserWindow w in (ShellFolderView) exShell.Windows())更具有逻辑意义,但不幸的是ShellFolderView并未实现IEnumerable,因此,没有foreach:(

无论如何,这是一种非常快速的方法(200毫秒),用于选择并闪烁已打开的正确浏览器窗口。

答案 2 :(得分:0)

我发现也可以使用file://协议,当你这样做时,如果文件夹已经打开,Windows似乎会关注该文件夹,而不是打开另一个窗口

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

答案 3 :(得分:0)

对我来说,这里的解决方案都不适用于 Win10。对于 Marcelo 的解决方案 exShell.Windows() 始终为空,Josh 的解决方案不适用于目录,您将收到 file does not exist 错误,而 nos 的解决方案抛出 access denied 错误。

这是我的工作解决方案:

    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 资源管理器具有窗口类 CabinetWClass 并将标题设置为浏览目录。

因此上面的代码检查是否存在具有特定目录的资源管理器窗口。

如果确实存在,则将窗口置于最前面,否则将使用指定目录启动一个新的 explorer 实例。请注意,您需要使用作为参数给出的路径专门开始 explorer.exe,否则它会抛出 access denied 错误。