启动和关闭 explorer.exe 的实例
start and close instance of explorer.exe
当我尝试像这样从 c# 启动 explorer.exe 时,我有一个奇怪的行为:
ProcessStartInfo info = new ProcessStartInfo("explorer.exe", "E:");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();
process.WaitForExit(5000);
问题是:
异常似乎是正确的,因为此时 HasExited
returns 已经 true
。尽管如此,在任务管理器中创建的资源管理器实例仍然存在。
所以我不明白我的电话是做什么的。我原以为它会直接启动一个资源管理器的实例,但似乎不是,或者资源管理器以某种不同的方式工作。
我的第二个问题:如何以编程方式启动和停止一个新的特定资源管理器实例?
编辑
回答一些问题:
- 资源管理器选项
Launch Folder Windows in a separate process
设置为 true
- 创建的
process.Id
不在任务管理器中。例如:taskmanager 中显示的新资源管理器实例具有 PID 4968,而调试器显示 10752 作为创建(和退出)进程的 ID。
编辑: 这里是 taskmanager 在 ~12 次调试运行后的截图
这可能是因为有问题的 explorer.exe 进程已经退出。 Windows 使用多个资源管理器 windows 会做一些奇怪的事情,这取决于您设置的选项。默认情况下,如果我没记错的话,所有 windows 最终都会 运行 在一个进程中。
我要做的是输出您刚刚生成的进程的进程标识:
Console.WriteLine($"{process.Id} has exited {process.HasExited}");
然后看看任务管理器,看能不能找到对应的进程。我想 HasExited 是真的,所以你不会找到进程,但 window 会打开。
您可能必须将 process.EnableRaisingEvents
设置为 true
才能从 process.HasExited
获得有效答案,我想不起来了。
同时通过文件夹选项检查资源管理器中的设置,看看您是否在视图选项卡上启用了 Launch Folder Windows in a separate process
。
如果您确实找到了您的进程,您可以随时终止该进程并查看您的 windows 是否关闭。如果是,则可能是 explorer.exe 没有创建主 window 句柄,您可以使用 Spy++
检查它
编辑了更多信息
此外,@Hans Passant 上面提到 shell windows 工作不同。所以实际发生的是,explorer.exe (1234)
联系根 explorer.exe (321)
,然后根 explorer.exe (321)
创建一个新的 window(如果 Launch separate 为 false)或产生一个子进程 explorer.exe (3445)
。您的进程 explorer.exe (1234)
已完成其工作,然后退出。您的进程从未创建 window,因此 CloseMainWindow()
将找不到要关闭的 window 和错误。
如何关闭特定的资源管理器window
为此,您需要利用 ShellWindows,请参阅 Is there a way to close a particular instance of explorer with C#?
作为参考,那里使用的代码是:
ShellWindows _shellWindows = new SHDocVw.ShellWindows();
string processType;
foreach (InternetExplorer ie in _shellWindows)
{
//this parses the name of the process
processType = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
//this could also be used for IE windows with processType of "iexplore"
if (processType.Equals("explorer") && ie.LocationURL.Contains(@"C:/Users/Bob"))
{
ie.Quit();
}
}
请注意,您需要注意不要关闭用户一开始想要打开的 window。是否有理由关闭 window?
问题出在 has UI Interface
的概念上,根据定义:
Closes a process that has a user interface by sending a close message
to its main window.
然而 explorer.exe
比使用 UI 的简单过程要复杂得多。
例如,如果您使用另一个更简单的应用程序(例如记事本),则不会引发异常:
ProcessStartInfo info = new ProcessStartInfo("notepad.exe");
info.WindowStyle = ProcessWindowStyle.Maximized;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();
当我尝试像这样从 c# 启动 explorer.exe 时,我有一个奇怪的行为:
ProcessStartInfo info = new ProcessStartInfo("explorer.exe", "E:");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();
process.WaitForExit(5000);
问题是:
异常似乎是正确的,因为此时 HasExited
returns 已经 true
。尽管如此,在任务管理器中创建的资源管理器实例仍然存在。
所以我不明白我的电话是做什么的。我原以为它会直接启动一个资源管理器的实例,但似乎不是,或者资源管理器以某种不同的方式工作。
我的第二个问题:如何以编程方式启动和停止一个新的特定资源管理器实例?
编辑 回答一些问题:
- 资源管理器选项
Launch Folder Windows in a separate process
设置为 true - 创建的
process.Id
不在任务管理器中。例如:taskmanager 中显示的新资源管理器实例具有 PID 4968,而调试器显示 10752 作为创建(和退出)进程的 ID。
编辑: 这里是 taskmanager 在 ~12 次调试运行后的截图
这可能是因为有问题的 explorer.exe 进程已经退出。 Windows 使用多个资源管理器 windows 会做一些奇怪的事情,这取决于您设置的选项。默认情况下,如果我没记错的话,所有 windows 最终都会 运行 在一个进程中。
我要做的是输出您刚刚生成的进程的进程标识:
Console.WriteLine($"{process.Id} has exited {process.HasExited}");
然后看看任务管理器,看能不能找到对应的进程。我想 HasExited 是真的,所以你不会找到进程,但 window 会打开。
您可能必须将 process.EnableRaisingEvents
设置为 true
才能从 process.HasExited
获得有效答案,我想不起来了。
同时通过文件夹选项检查资源管理器中的设置,看看您是否在视图选项卡上启用了 Launch Folder Windows in a separate process
。
如果您确实找到了您的进程,您可以随时终止该进程并查看您的 windows 是否关闭。如果是,则可能是 explorer.exe 没有创建主 window 句柄,您可以使用 Spy++
检查它编辑了更多信息
此外,@Hans Passant 上面提到 shell windows 工作不同。所以实际发生的是,explorer.exe (1234)
联系根 explorer.exe (321)
,然后根 explorer.exe (321)
创建一个新的 window(如果 Launch separate 为 false)或产生一个子进程 explorer.exe (3445)
。您的进程 explorer.exe (1234)
已完成其工作,然后退出。您的进程从未创建 window,因此 CloseMainWindow()
将找不到要关闭的 window 和错误。
如何关闭特定的资源管理器window
为此,您需要利用 ShellWindows,请参阅 Is there a way to close a particular instance of explorer with C#?
作为参考,那里使用的代码是:
ShellWindows _shellWindows = new SHDocVw.ShellWindows();
string processType;
foreach (InternetExplorer ie in _shellWindows)
{
//this parses the name of the process
processType = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
//this could also be used for IE windows with processType of "iexplore"
if (processType.Equals("explorer") && ie.LocationURL.Contains(@"C:/Users/Bob"))
{
ie.Quit();
}
}
请注意,您需要注意不要关闭用户一开始想要打开的 window。是否有理由关闭 window?
问题出在 has UI Interface
的概念上,根据定义:
Closes a process that has a user interface by sending a close message to its main window.
然而 explorer.exe
比使用 UI 的简单过程要复杂得多。
例如,如果您使用另一个更简单的应用程序(例如记事本),则不会引发异常:
ProcessStartInfo info = new ProcessStartInfo("notepad.exe");
info.WindowStyle = ProcessWindowStyle.Maximized;
Process process = new Process();
process.StartInfo = info;
process.Start();
Thread.Sleep(2000);
bool res = process.CloseMainWindow(); // InvalidOperationException -> already exited
process.Close();