Проблема с Killing Windows Explorer? - PullRequest
5 голосов
/ 03 апреля 2010

Мне нужно убить процесс проводника Windows (explorer.exe), для этого

допустим, я использую нативный метод NT TerminateProcess

Это работает, но проблема в том, что проводник запускается снова, может быть, Windows делает это, в любом случае. Когда я убиваю explorer.exe с помощью диспетчера задач Windows, он не возвращается, он остается убитым.

Я хочу делать все, что менеджер задач выполняет через мое приложение.

Edit:
Благодаря @sblom я решил это, быстрое изменение реестра помогло. Хотя это умный хак, очевидно, у taskmnager есть более чистый способ сделать это, тем не менее, я решил пока пойти по пути @ sblom.

Ответы [ 5 ]

14 голосов
/ 03 апреля 2010

С Technet :

Вы можете установить ключ реестра HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoRestartShell на 0, и он больше не будет автоматически перезагружаться.

8 голосов
/ 03 апреля 2010

«Настоящее» решение. (Полная программа. Проверено для работы на 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;
        }
    }
}
5 голосов
/ 21 октября 2012

Вот еще одно решение этой проблемы - вместо вызовов 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 Explorer.

Я добавил его как метод расширения, чтобы вы могли использовать его непосредственно в объекте Process:

    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).

РЕДАКТИРОВАТЬ: Исходная ссылка не работает, заменена на кэш из Internet Archive Wayback Machine. Обновленную документацию для Windows 2012/2016 можно найти по адресу: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill

2 голосов
/ 03 апреля 2010

Что вам, вероятно, нужно сделать, вместо того, чтобы использовать TerminateProcess, отправить сообщение WM_QUIT в окна проводника и основной поток. Это немного запутанно, но я нашел эту страницу, на которой есть пример кода, который может вам помочь:

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

Windows автоматически перезапустит explorer.exe после TerminateProcess, чтобы он перезапустился в случае завершения сбоя.

0 голосов
/ 09 марта 2015

У меня есть некоторые исследования, и это остатки:

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 для запуска приложения от имени администратора, как описано в этом Ответе . И если UAC выключен, я направляю вас на этот Ответ .
  • Вы можете встроить файл манифеста в exe, что приведет к тому, что Windows Seven всегда будет запускать программу от имени администратора, как объясняется в этом Ответ .
  • Вы должны знать, что не можете заставить ваш процесс запускаться от имени администратора; так что вы можете запустить свой процесс внутри вашего процесса как другой процесс! Вы можете использовать это сообщение в блоге или этот ответ .
  • Вы также можете использовать команду reg с этой [Документацией Microsoft Windows]. 6 .

После установки этого параметра - перезапуск проводника - off: этот код может закрыться explorer:

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