如何以编程方式重新启动 Windows 资源管理器进程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/565405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to programmatically restart windows explorer process
提问by Benoit
I'm working on a windows shell extension, and unfortunately, when making changes to the DLL, I must restart windows explorer (since it keeps the DLL in memory).
我正在开发 Windows shell 扩展,不幸的是,在更改 DLL 时,我必须重新启动 Windows 资源管理器(因为它将 DLL 保留在内存中)。
I found this program from Dino Esposito, but it doesn't work for me.
我从 Dino Esposito 找到了这个程序,但它对我不起作用。
void SHShellRestart(void)
{
HWND hwnd;
hwnd = FindWindow("Progman", NULL );
PostMessage(hwnd, WM_QUIT, 0, 0 );
ShellExecute(NULL, NULL, "explorer.exe", NULL, NULL, SW_SHOW );
return;
}
Does any one have something they can share to do this?
有没有人可以分享一些东西来做到这一点?
P.S. I realize that I can go to task manager and kill the explorer process, but I just want to do it the lazy way. Besides, this enables automation.
PS我意识到我可以去任务管理器并杀死资源管理器进程,但我只想以懒惰的方式做到这一点。此外,这可以实现自动化。
P.P.S I am using .NET for the development, but the shell restart functionality could be in C, C++ or a .NET language. It will simply be a small stand-alone executable.
PPS 我使用 .NET 进行开发,但外壳重启功能可以是 C、C++ 或 .NET 语言。它只是一个小的独立可执行文件。
采纳答案by wj32
A fool-proof solution:
一个万无一失的解决方案:
foreach (Process p in Process.GetProcesses())
{
// In case we get Access Denied
try
{
if (p.MainModule.FileName.ToLower().EndsWith(":\windows\explorer.exe"))
{
p.Kill();
break;
}
}
catch
{ }
}
Process.Start("explorer.exe");
回答by Chuck Rostance
After parsing some of the earlier answers and doing a bit of research, I've created a little complete example in C#. This closes the explorer shell then waits for it to completely shut down and restarts it. Hope this helps, there's a lot of interesting info in this thread.
在解析了一些早期的答案并做了一些研究之后,我在 C# 中创建了一个完整的例子。这将关闭资源管理器外壳,然后等待它完全关闭并重新启动它。希望这会有所帮助,这个线程中有很多有趣的信息。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace RestartExplorer
{
class Program
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)] uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
const int WM_USER = 0x0400; //http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931(v=vs.85).aspx
static void Main(string[] args)
{
try
{
var ptr = FindWindow("Shell_TrayWnd", null);
Console.WriteLine("INIT PTR: {0}", ptr.ToInt32());
PostMessage(ptr, WM_USER + 436, (IntPtr)0, (IntPtr)0);
do
{
ptr = FindWindow("Shell_TrayWnd", null);
Console.WriteLine("PTR: {0}", ptr.ToInt32());
if (ptr.ToInt32() == 0)
{
Console.WriteLine("Success. Breaking out of loop.");
break;
}
Thread.Sleep(1000);
} while (true);
}
catch (Exception ex)
{
Console.WriteLine("{0} {1}", ex.Message, ex.StackTrace);
}
Console.WriteLine("Restarting the shell.");
string explorer = string.Format("{0}\{1}", Environment.GetEnvironmentVariable("WINDIR"), "explorer.exe");
Process process = new Process();
process.StartInfo.FileName = explorer;
process.StartInfo.UseShellExecute = true;
process.Start();
Console.ReadLine();
}
}
}
回答by CappuccinoRob
I noticed no one addressed the issue of starting explorer.exe as the shell, rather than it just opening an explorer window. Took me a while to figure this out, turns out it was something simple:
我注意到没有人解决将 explorer.exe 作为 shell 启动的问题,而不仅仅是打开一个资源管理器窗口。我花了一段时间才弄清楚这一点,结果很简单:
string explorer = string.Format("{0}\{1}", Environment.GetEnvironmentVariable("WINDIR"), "explorer.exe");
Process process = new Process();
process.StartInfo.FileName = explorer;
process.StartInfo.UseShellExecute = true;
process.Start();
You have to set the StartInfo.UseshellExecute as true to get it to restart as the shell.
您必须将 StartInfo.UseshellExecute 设置为 true 才能让它作为 shell 重新启动。
回答by vhanla
This is for Windows 7/8 (and need testing, maybe even works on Vista).
这适用于 Windows 7/8(需要测试,甚至可能适用于 Vista)。
Since there is a proper way to close Explorer(progman) included in Windows 7 & 8 - by right clickingthe taskbar (Shell_TrayWnd in Win8 or StartMenu on Win7) while pressing Ctrl-Shift, it shows in the popup menu a hidden option to close Explorer, and digging it using Spy++ it is triggered by message WM_USER+436.
由于有一种正确的方法可以关闭Windows 7 和 8 中包含的资源管理器(progman) -通过右键单击任务栏(Win8 中的 Shell_TrayWnd 或 Win7 中的 StartMenu)同时按 Ctrl-Shift,它会在弹出菜单中显示一个隐藏的关闭选项Explorer,并使用 Spy++ 挖掘它是由消息WM_USER+436触发的。
So I tested and doing the following it works great.
所以我测试并执行以下操作,效果很好。
PostMessage(FindWindow('Shell_TrayWnd'),nil),WM_USER+436,0,0);
It closes Explorer, with all the opened instances. And to relaunch explorer, use the methods provided above.
它关闭资源管理器,以及所有打开的实例。要重新启动资源管理器,请使用上面提供的方法。
So, please confirmin comments if this works on 32bit/64bit editions of your windows vista/7/8 or any other.
因此,请在评论中确认这是否适用于您的 windows vista/7/8 或任何其他版本的 32 位/64 位版本。
回答by sharptooth
After FindWindow use GetWindowThreadProcessId, then OpenProcess, then TerminateProcess.
在 FindWindow 之后使用 GetWindowThreadProcessId,然后是 OpenProcess,然后是 TerminateProcess。
回答by Benoit
After some more googling, I came up with the following C# solution:
经过更多的谷歌搜索,我想出了以下 C# 解决方案:
using System.Diagnostics;
...
static public void RestartExplorer()
{
foreach(Process p in Process.GetProcesses()) {
if(p.MainModule.ModuleName.contains("explorer") == true)
p.Kill();
}
Process.Start("explorer.exe");
}
回答by Bob Moore
This works for me on Vista:
这在 Vista 上对我有用:
DWORD dwPID;
HANDLE hExp;
HWND hSysTray = ::FindWindow (TEXT("Shell_TrayWnd"), NULL) ;
GetWindowThreadProcessId (hSysTray, &dwPID);
hExp = OpenProcess (PROCESS_TERMINATE, FALSE, dwPID);
if (hExp)
{
TerminateProcess (hExp, 0);
}
Sleep (2000);
ShellExecute (NULL, NULL, TEXT("explorer.exe"), NULL, NULL, SW_HIDE);
But I can't find any way to suppress the explore window that opens (I tried, hence the SW_HIDE). On Vista, running explorer.exe without parameters seems to be the same as running "explorer.exe /e" on earlier systems. You'll have to try it for yourself on XP, I don't have it here.
但是我找不到任何方法来抑制打开的探索窗口(我尝试过,因此是 SW_HIDE)。在 Vista 上,不带参数运行 explorer.exe 似乎与在早期系统上运行“explorer.exe /e”相同。您必须在 XP 上亲自尝试,我这里没有。
Note: Using TerminateProcess does seem extreme, but posting a WM_CLOSE to explorer provokes a windows shutdown dialog.
注意:使用 TerminateProcess 确实看起来很极端,但是向资源管理器发布 WM_CLOSE 会引发 Windows 关闭对话框。
回答by dalek9
A C# solution that provides more certainty that the "right" explorer processes get killed.
AC# 解决方案提供了更多的确定性,即“正确的”资源管理器进程被杀死。
using System;
using System.Diagnostics;
...............
public static void RestartExplorer()
{
const string explorer = "explorer.exe";
string explorerPath = string.Format("{0}\{1}", Environment.GetEnvironmentVariable("WINDIR"), explorer);
foreach (Process process in Process.GetProcesses())
{
// In case we get Access Denied
try
{
if (string.Compare(process.MainModule.FileName, explorerPath, StringComparison.OrdinalIgnoreCase) == 0)
{
process.Kill();
}
}
catch
{
}
}
Process.Start(explorer);
}