【问题标题】:If Windows explorer is open at a specific path, do not create a new instance如果 Windows 资源管理器在特定路径打开,请不要创建新实例
【发布时间】:2015-11-20 12:32:03
【问题描述】:

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

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

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

【问题讨论】:

  • 然后不启动一个新实例,找到现有的窗口并将其带到前台
  • @PanagiotisKanavos 这就是问题所在。我怎么知道它是否已经打开?
  • @disasterkid,看看我的回答是否已经打开。

标签: c# process windows-explorer


【解决方案1】:

您可以使用“打开”动词,它会在资源管理器中打开目录,如果您将一个已经打开的目录传递给它,则可以重新使用现有的 explorer.exe: 所以,假设Conf.FilesLocation 是一个目录:

        var proc = new ProcessStartInfo();
        proc.FileName = Conf.FilesLocation;
        proc.Verb = "open";
        proc.WindowStyle = ProcessWindowStyle.Hidden;
        Process.Start(proc );

【讨论】:

  • proc.WindowStyle = ProcessWindowStyle.Hidden; 行导致无法打开 explorer.exe,必须删除。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    虽然@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 毫秒)的方式来选择并闪烁正确的已打开的资源管理器窗口。

    【讨论】:

      【解决方案4】:

      对我来说,这里的解决方案都不适用于 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.exe,否则会抛出 access denied 错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多