如何以编程方式重新启动 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:00:16  来源:igfitidea点击:

How to programmatically restart windows explorer process

.netwindowswinapiexplorerwindows-explorer

提问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);
 }