如何以编程方式重新启动Windows资源管理器进程

时间:2009-02-19 13:54:13

标签: .net windows winapi explorer windows-explorer

我正在开发一个Windows shell扩展,不幸的是,在更改DLL时,我必须重新启动Windows资源管理器(因为它将DLL保存在内存中)。

我从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;
}

是否有人可以分享他们可以分享的内容?

P.S。我意识到我可以去任务管理器并杀死资源管理器进程,但我只是想以懒惰的方式去做。此外,这可实现自动化。

P.P.S我使用.NET进行开发,但shell重启功能可以是C,C ++或.NET语言。它只是一个小型的独立可执行文件。

9 个答案:

答案 0 :(得分:10)

在解析了一些早期的答案并做了一些研究之后,我在C#中创建了一个完整的例子。这将关闭资源管理器shell,然后等待它完全关闭并重新启动它。希望这会有所帮助,这个帖子中有很多有趣的信息。

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();

    }
}
}

答案 1 :(得分:6)

我注意到没有人解决启动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();

您必须将StartInfo.UseshellExecute设置为true才能使其作为shell重新启动。

答案 2 :(得分:5)

一个万无一失的解决方案:

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");

答案 3 :(得分:1)

在FindWindow之后使用GetWindowThreadProcessId,然后使用OpenProcess,然后使用TerminateProcess。

答案 4 :(得分:1)

经过一番谷歌搜索后,我想出了以下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");
}

答案 5 :(得分:1)

这适用于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);

但是我找不到任何方法来抑制打开的探索窗口(我试过,因此SW_HIDE)。在Vista上,运行不带参数的explorer.exe似乎与在早期系统上运行“explorer.exe / e”相同。你必须在XP上自己尝试一下,我没有在这里。

注意:使用TerminateProcess看起来确实极端,但是向资源管理器发布WM_CLOSE会引发Windows关闭对话框。

答案 6 :(得分:1)

这适用于Windows 7/8(需要测试,甚至可能适用于Vista)。

由于有一种正确的方法可以关闭Windows 7和Windows 7中包含的Explorer (progman)。 8 - 右键单击任务栏(Win8中的Shell_TrayWnd或Win7上的StartMenu),同时按Ctrl-Shift ,它会在弹出菜单中显示关闭的隐藏选项资源管理器,并使用Spy ++挖掘它,它由消息 WM_USER + 436 触发。

所以我测试并做了以下工作,效果很好。

PostMessage(FindWindow('Shell_TrayWnd'),nil),WM_USER+436,0,0);

它会关闭所有已打开实例的资源管理器。要重新启动资源管理器,请使用上面提供的方法。

因此,请在评论中确认,如果这适用于Windows Vista / 7/8或其他任何版本的32位/ 64位版本。

答案 7 :(得分:0)

一种C#解决方案,可以更加确定“正确”的资源管理器进程被杀死。

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

答案 8 :(得分:0)

我不知道这是否适用于所有人,但是在我的PC上为我工作时,我的系统是win10。可以用cmd.exe单词解决。调用tskill命令。

Process.Start("cmd.exe", "/s /c tskill explorer");

如果您不想看到它cmd.exe,如果黑色窗口闪烁,您可以使用以下代码

ProcessStartInfo info = new ProcessStartInfo {
    FileName = "cmd.exe",
    Arguments = "/s /c tskill explorer",
    WindowStyle = ProcessWindowStyle.Hidden,
    UseShellExecute = true
};
new Process { StartInfo = info }.Start();

现在我认为最好的方法是:

using(Process process = new Process())
{
    process.StartInfo = new ProcessStartInfo
    {
        FileName = "cmd.exe",
        Arguments = "/c taskkill -f -im explorer.exe",
        WindowStyle = ProcessWindowStyle.Hidden,
        UseShellExecute = true
    };
    process.Start();
    process.WaitForExit();
    process.StartInfo.Arguments = "/c explorer";
    process.Start();
}