代码之家  ›  专栏  ›  技术社区  ›  Vivek Bernard

终止Windows资源管理器有问题吗?

  •  5
  • Vivek Bernard  · 技术社区  · 14 年前

    为此,我需要终止Windows资源管理器的进程(explorer.exe)

    假设我使用本机nt方法terminateprocess

    它可以工作,但问题是资源管理器再次启动,可能是Windows正在这样做,无论如何。当我用windows任务管理器杀死explorer.exe时,它不会回来,它的停留也会被杀死。

    我想通过我的应用程序做taskmanager正在做的任何事情。

    编辑:
    多亏了@sblom我解决了这个问题,注册表中的一个快速调整就成功了。虽然这是一个聪明的方法,但显然taskmnager有一个更干净的方法,也就是说,我决定暂时采用@sblom的方法。

    5 回复  |  直到 6 年前
        1
  •  8
  •   sblom    14 年前

    真正的解决方案。(完成程序。已测试可在Windows 7上运行。)

    using System;
    using System.Runtime.InteropServices;
    
    namespace ExplorerZap
    {
        class Program
        {
            [DllImport("user32.dll")]
            public static extern int FindWindow(string lpClassName, string lpWindowName);
            [DllImport("user32.dll")]
            public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
    
            [return: MarshalAs(UnmanagedType.Bool)]
            [DllImport("user32.dll", SetLastError = true)]
            public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam);
    
            static void Main(string[] args)
            {
                int hwnd;
                hwnd = FindWindow("Progman", null);
                PostMessage(hwnd, /*WM_QUIT*/ 0x12, 0, 0);
                return;
            }
        }
    }
    
        2
  •  14
  •   sblom    14 年前

    Technet :

    您可以设置注册表项 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoRestartShell 到0,它将不再自动重新启动。

        3
  •  5
  •   Frode Evensen David M    6 年前

    下面是解决此问题的另一个解决方案-相反,API调用它使用Windows附带的外部工具(至少Win 7 Professional):

        public static class Extensions
        {
            public static void ForceKill(this Process process)
            {
                using (Process killer = new Process())
                {
                    killer.StartInfo.FileName = "taskkill";
                    killer.StartInfo.Arguments = string.Format("/f /PID {0}", process.Id);
                    killer.StartInfo.CreateNoWindow = true;
                    killer.StartInfo.UseShellExecute = false;
                    killer.Start();
                    killer.WaitForExit();
                    if (killer.ExitCode != 0)
                    {
                        throw new Win32Exception(killer.ExitCode);
                    }
                }
            }
        }
    

    我知道win32exception可能不是最好的异常,但是这个方法的行为或多或少类似于kill,只是它实际上杀死了windows资源管理器。

    我已将其添加为扩展方法,因此您可以直接在流程对象上使用它:

        foreach (Process process in Process.GetProcessesByName("explorer"))
        {
            process.ForceKill();
        }
    

    您必须首先确保taskkill工具在生产环境中可用(在windows中似乎已经有一段时间了: https://web.archive.org/web/20171016213040/http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/taskkill.mspx?mfr=true )

    编辑: 原来的链接死了,取而代之的是来自互联网存档的缓存回退机。有关Windows 2012/2016的更新文档,请访问: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill

        4
  •  2
  •   Gerald    14 年前

    您可能需要做的是,不要使用terminateprocess,而是向explorer窗口和主线程发送wm_quit消息。这有点复杂,但我发现这一页有一些示例代码可以帮助您:

    http://www.replicator.org/node/100

    Windows将在终止进程后自动重新启动explorer.exe,以便在崩溃终止时重新启动。

        5
  •  0
  •   Community CDub    7 年前

    我做了一些研究,结果如下:

    Windows将重新启动 explorer 在它关闭之后- 任务管理器除外 -

    所以你应该把相关的 RegistryKey :

    RegistryKey regKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default).OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\Winlogon", RegistryKeyPermissionCheck.ReadWriteSubTree);
    if (regKey.GetValue("AutoRestartShell").ToString() == "1")
        regKey.SetValue("AutoRestartShell", 0, RegistryValueKind.DWord);
    

    要更改注册表项,程序应以管理员身份运行:

    • 您可以向用户显示uac提示以管理员身份运行应用程序,如下所述 Answer . 如果UAC关闭,我会告诉你 Answer .
    • 您可以在 exe ,这将导致Windows7始终以管理员身份运行该程序,如下所述 Answer .
    • 您应该知道,您不能强制以管理员身份启动流程;因此,您可以在流程中以另一个流程的形式运行流程!你可以用这个 blog post 或者这个 answer .
    • 你也可以使用 reg 使用此命令[Microsoft Windows文档]。 6 .

    设置之后- 重新启动资源管理器 -关闭:此代码可以关闭 探险家 :

    Process[] ps = Process.GetProcessesByName("explorer");
    foreach (Process p in ps)
        p.Kill();