使用 Process.Start 打开资源管理器窗口会创建过多的 explorer.exe 进程

Posted

技术标签:

【中文标题】使用 Process.Start 打开资源管理器窗口会创建过多的 explorer.exe 进程【英文标题】:Open an Explorer window with Process.Start creates excessive explorer.exe processes 【发布时间】:2020-08-06 18:43:18 【问题描述】:

当我使用目录路径启动资源管理器窗口时,会生成一个新的 explorer.exe 进程。在我的程序退出后,explorer.exe 进程保持打开状态,这没关系,但是当我关闭该资源管理器窗口时,进程并没有关闭。如果我在我的程序中生成了多个资源管理器窗口,我最终会得到许多 explorer.exe 进程,即使所有资源管理器窗口都已关闭。

ProcessStartInfo startInfo = new ProcessStartInfo("explorer.exe", folderPath);
Process.Start(startInfo);

但是,如果我只启动 explorer.exe 而没有第二个参数,即使打开了资源管理器窗口,也不会创建额外的 explorer.exe 进程。当该探索窗口关闭时,除了桌面进程之外,您也看不到任何额外的 explorer.exe 进程。请注意,我的桌面 explore.exe 是 PID 7704 是这个示例,应该是唯一一个正在运行的示例。

ProcessStartInfo startInfo = new ProcessStartInfo("explorer.exe", folderPath);
Process.Start(startInfo);

我发现,如果我使用 cmd.exe 手动执行此启动操作,这是正确的。在命令提示符下,如果您运行“explorer.exe C:/”,则可以创建相同的“悬空” explorer.exe 进程,而只运行“explorer.exe”则不会。

所以我的问题是如何在不创建所有这些额外 explorer.exe 进程的情况下为我想要的文件夹打开资源管理器窗口。我还想知道“悬空”的 explorer.exe 进程是否最终会自行消失,或者它们会坐在那里并占用所有内存,直到我不得不强制结束任务。到目前为止,我已经看到它们持续了好几天并且从未消失,即使在关闭窗口后不再有与它们关联的资源管理器窗口。

到目前为止,我唯一能想到的就是打开一个不带参数的 explorer.exe,这样它就不会创建额外的进程,然后以某种方式找到打开的资源管理器窗口句柄,然后使用它浏览到我想要的目录。我见过一些 DLLImport("user32.dll") 可能能够做到这一点。

这听起来比只使用 Process.Start 来立即访问我想要的文件夹要困难得多。我只是不认为我的程序留下大量的内存消耗进程不是一个好主意,即使这是你已经可以用 cmd.exe 做的事情。我不知道这是否是最终导致内存不足的 Windows“功能”。

【问题讨论】:

this 有帮助吗? 捕获您创建的“explorer.exe”的进程ID。完成后,通过识别进程 ID 来终止进程。 不幸的是,没有。它和我的代码做同样的事情。它仍然会启动 explorer.exe 的额外进程,并且关闭资源管理器窗口不会结束该进程。 @mjb,之后我无法终止该进程,因为我的程序通常已经消失。用户打开文件夹以浏览他们想要的目录,但即使我的程序长时间终止,他们通常也不会关闭文件夹。问题是这些额外的 explorer.exe 进程即使在用户关闭资源管理器窗口后仍然存在(无论我的程序是否仍然存在)。 【参考方案1】:

这是一种解决方案,它不创建额外的 explorer.exe 进程,而是使用现有的进程。

我在从命令行打开文件夹时意识到了这一点。运行“explorer c:\temp”时,会创建一个新的 explorer.exe。但是当运行"start c:\temp"..

所以下面的代码启动了一个隐藏的 cmd 进程,用"start <folder>\r\n" 输入它的输入,然后用"exit\r\n" 关闭它。代码还会检查新的 cmd 进程是否泄露。

希望这会有所帮助。

Process cmd = new Process()

    StartInfo = new ProcessStartInfo()
    
        FileName = "cmd",
        CreateNoWindow = true,
        UseShellExecute = false,
        RedirectStandardInput = true
    
;
cmd.Start();
int processId = cmd.Id;
Debug.WriteLine("PID: 0", processId);
cmd.StandardInput.Write("start " + folderPath + "\r\n");
cmd.StandardInput.Write("exit\r\n");
cmd = null;

try

    Process isCmdStillThere = Process.GetProcessById(processId);

catch (Exception errorQueryingProcess)

    Debug.Assert(errorQueryingProcess.Message == "Process with an Id of " + processId + " is not running.");

【讨论】:

这行得通,但问题是它依赖于 cmd.exe 来打开文件夹。这变得有问题,因为此处由 Process 调用的 cmd.exe 没有关联的帐户权限,没有“以管理员身份运行”选项,您可以通过在 GUI 模式下启动它之前右键单击 cmd.exe 来完成。这意味着我无法打开需要用户级别身份验证的网络文件夹位置。有没有办法以管理员权限启动它? 但是感谢您的回答,因为它教会了我一些关于 cmd.exe 的新知识。 如果要打开任何包含空格的目录,正确的语法是:start "Title" "Directory path"【参考方案2】:

我只是碰巧刚刚做了这样的事情,也许有帮助

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) 
Process::Start("explorer.exe", "/open, C:\\Users\\mywindows\\source\\repos\\Kuliah\\Debug\\Praktikum Pertemuan 2.exe");

别忘了添加库

using namespace System::Diagnostics;

试试简单的代码

Process::Start("explorer.exe");

【讨论】:

以上是关于使用 Process.Start 打开资源管理器窗口会创建过多的 explorer.exe 进程的主要内容,如果未能解决你的问题,请参考以下文章

C# Process.Start()方法详解

WinForm 进程线程

如何从 .NET 程序打开 Web 浏览器? Process.Start() 不起作用?

System.Diagnostics.Process 启动进程资源或调用外部的命令的使用

Process.Start() 打开 URL 有时会抛出 Win32Exception?

Core 3.0 中的 Process.Start 不会仅按名称打开文件夹