Завершение работы процесса

      Данная статья рассматривает три примера реализации завершения работы выбранного процесса, как с использованием его имени, так и идентификатора.
  • Пример №1 – использование метода «Kill» из класса «System.Diagnostics»;
  • Пример №2 – завершение процессов по идентификаторам или именам исполняемых файлов на локальной или удаленной системе с использованием команды «TASKKILL»;
  • Пример №3 – использование Windows API функции «TerminateProcess» из библиотеки «Kernel32.lib».
Пример №1

      В данном примере используется метод «Kill» из класса «System.Diagnostics». «Kill» вызывает аварийное завершение процесса и должен использоваться только при необходимости.
      Данные, измененные процессом или ресурсами, выделенными для процесса, могут быть потеряны, если вызвать метод «Kill». Так же в данном классе присутствует метод «CloseMainWindow», который позволяет выполнить остановку процесса и закрыть все окна, поэтому является предпочтительным для приложений с интерфейсом. Запрос на завершение процесса вызовом метода «CloseMainWindow» не вынудит приложение завершиться. Приложение может запросить проверку пользователя до закрытия или может отказаться закрыться. В данном случае для того чтобы вынудить приложение закрыться, следует использовать метод «Kill».
      Метод «Kill» выполняется асинхронно. После вызова метода «Kill» следует вызвать метод «WaitForExit» для ожидания завершения процесса или проверить свойство «HasExited», чтобы определить, завершился ли процесс.

//Немедленно останавливаем 
//выбранный процесс.
clsProcess.Kill();
//Ждем завершения процесса.
clsProcess.WaitForExit();
//Выполняем проверку если работающий системный процесс,
//на который ссылается компонент
//System.Diagnostics.Process, был завершен возвращаем true;
//в противном случае — значение false.                        
if (clsProcess.HasExited) 
    return true;
else
    return false;
      Методы «Kill» и «CloseMainWindow» можно вызывать только для процессов, выполняющихся на локальном компьютере. Для удаленного компьютера можно только просматривать информацию о процессах. Если метод «Kill» вызван во время закрытия текущего процесса, создается Win32Exception с описанием ошибки: "Доступ запрещен".
      Создайте проект «Windows Form» в «Microsoft Visual Studio» и добавьте на главную форму вашего проекта элементы управления «comboBox» и «button». Первый будет отвечать за вывод списка имен запущенных в данный момент процессов, а второй выполнять вызов метода закрытия выбранного процесса. У вас получится приведенный ниже пример.
      Сделайте двойной клик левой клавишей мыши по любому свободному месту главной формы, вы перейдете в редактор кода с установкой курсора в автоматически созданном методе «Form1_Load», события «Load», выполняющегося при загрузке формы. Вставьте в тело данного метода приведенный ниже код, вызова метода получения списка имен, запущенных процессов.
ProcessList();
Так же добавьте приведённый ниже код самого метода «ProcessList».
private void ProcessList()
{
    //Получаем массив типа System.Diagnostics.Process,
    //предоставляющий данные обо всех процессах,
    //выполняющегося на локальном компьютере.
    System.Diagnostics.Process[] processlist =
        System.Diagnostics.Process.GetProcesses();
    //Выполняем поиск всех процессов в полученном массиве
    //и добавляем их имена в элемент управления comboBox1.
    foreach(System.Diagnostics.Process theprocess in processlist)
    {
        //Добавляем имя текущего процесса
        //в элемент управления comboBox1.
        comboBox1.Items.Add(theprocess.ProcessName);
    }
}
      Перейдите в конструктор главной формы и сделайте двойной клик левой клавишей мыши по элементу управления «button1». Вы перейдете в редактор кода с автоматической установкой курсора в созданном методе «button1_Click», события «Click», возникающего при нажатии на кнопку. Добавьте приведенный ниже листинг, реализующий вызов метода «FindAndKillProcess», выполняющего поиск и завершение выбранного процесса в элементе управления «comboBox1». А так же возвращающего значение «true», если процесс был успешно завершён, иначе «false», с выводом информации о результате в сообщении.
//Вызываем метод поиска и завершения выбранного процесса.
if (FindAndKillProcess(comboBox1.Text))
{
    MessageBox.Show("Процесс успешно завершён!", "Завершение процесса",
        MessageBoxButtons.OK, MessageBoxIcon.Information);
    //Очищаем устаревший список процессов.
    comboBox1.Items.Clear();
    //Очищаем поле ввода.
    comboBox1.Text = "";
    //Загружаем новый.
    ProcessList();
}
else
    MessageBox.Show("Ошибка при завершении процесса.", "Завершение процесса",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
Добавьте приведенный ниже код метода «FindAndKillProcess» в листинг главной формы.
public bool FindAndKillProcess(string name)
{
    try
    {
        //Проходимся по всем процессам локального компьютера.
        foreach (System.Diagnostics.Process clsProcess in 
                           System.Diagnostics.Process.GetProcesses())
        {
            //Определяем, совпадает ли начало имени процесса с указанным.
            //Если да, то метод "StartsWith" возвращает значение true
            //и вызывается метод удаления процесса,
            //в противном случае — значение false и происходит
            //переход к следующему процессу.
            if (clsProcess.ProcessName.StartsWith(name))
            {
                //Немедленно останавливаем 
                //выбранный процесс.
                clsProcess.Kill();
                //Ждем завершения процесса.
                clsProcess.WaitForExit();
                //Выполняем проверку если работающий системный процесс,
                //на который ссылается компонент
                //System.Diagnostics.Process, был завершен возвращаем true;
                //в противном случае — значение false.                        
                if (clsProcess.HasExited) 
                    return true;
                else
                    return false;
            }
        }
        //Если процесс не был найден
        //возвращаем false.
        return false;
    }
    catch (Exception)
    {
        //При получении ошибок
        //возвращаем false.
        return false;
    }
}
      Запустите проект, нажав на клавишу «F5». После успешной компиляции и запуска вашего проекта у вас откроется главная форма проекта с заполненным списком имен запущенных в данный момент процессов.
      Выберете из выпадающего списка, имя процесса, завершение работы которого вы хотите выполнить и нажмите на кнопку «Завершить». В случае если программе удастся или нет выполнить завершение, вы получите сообщение с соответствующей информацией.

Пример №2

      Данный пример описывает завершение процессов по идентификаторам или именам исполняемых файлов на локальной или удаленной системе с использованием команды «TASKKILL». Команда может использоваться в операционных системах Windows XP и старше.

TASKKILL /F /IM notepad++.exe /T

  • /F - Принудительное завершение процесса.
  • /IM <имя процесса> - Имя образа процесса, который требуется завершить. Знак подстановки "*" может быть использован для указания всех заданий или имен образов.
  • /T - Завершение указанного процесса и всех его дочерних процессов.
      Так же можно выполнить завершение процесса по его идентификатору «PID», подставив соответственный ключ «/PID <процесс>». В случае если вам необходимо повысить свои привилегии при завершении работы процесса, вы можете воспользоваться ключами для указания учетных данных:
/U [<домен>\]<пользователь> /P <пароль>
Ниже представлены примеры реализации завершения работы процессов:
  • TASKKILL /IM notepad++.exe - завершение процесса, исполняемым образом которого является notepad.exe++. Если таких процессов более одного - то будут завершены все;
  • TASKKILL /PID 1568 /T - завершить процесс с идентификатором 1568 и все его дочерние процессы (/T) . Одной командой можно завершить несколько процессов, задавая их PID - taskkill /PID 1568 /PID 1569 /PID 1570;
  • TASKKILL /F /FI "PID ge 2015" /FI "WINDOWTITLE eq Arc*" - принудительно (/F) завершить процесс, идентификатор которого больше или равен 2000 и заголовок окна которого , начинается с текста Arc;
  • TASKKILL /F /FI "USERNAME eq NT AUTHORITY\SYSTEM" /IM notepad++.exe - принудительно завершить процесс, выполняющийся в контексте учетной записи NT AUTHORITY\SYSTEM и исполняемый файл которого имеет имя notepad.exe++;
  • TASKKILL /S 192.168.1.105 /U MyDomain\user /FI "USERNAME ne NT*" /IM * - завершить все процессы, выполняющиеся в контекстах учетных записей, не начинающихся со строки NT на компьютере с IP-адресом 192.168.0.243. При подключении к удаленной системе используется имя пользователя user в домене Mydomain. Пароль не задан и будет запрошен при выполнении команды;
  • TASKKILL /S SERVER /U Mydomain\User /P UserPass /FI "IMAGENAME eq note*" - завершить все процессы, имя исполняемого файла которых начинается со строки note на удаленном компьютере с именем SERVER.
Ниже приведен пример выполнения завершения процесса с использованием команды «TASKKILL».

try
{
    System.Diagnostics.Process.Start("taskkill", "/F /IM notepad++.exe* /T");              
}
catch (Exception msg_ex)
{
    MessageBox.Show(msg_ex.Message);
}

Пример №3

      В данном примере для завершения работы процесса используется Windows API функция «TerminateProcess» из библиотеки «Kernel32.lib». Функция не дает процессу ни малейшего шанса самому провести очистку, операционная система высвобождает все принадлежавшие ему ресурсы: возвращает себе выделенную им память, закрывает любые открытые файлы, уменьшает счетчики соответствующих объектов ядра и разрушает все его User- и GDI-объекты.
      После завершения процесса система гарантирует: после него ничего не останется — даже намеков на то, что он когда-то выполнялся. Завершенный процесс не оставляет за собой никаких следов. Синтаксис данной функции представлен ниже.

[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
        static extern bool TerminateProcess(int hProcess, uint uExitCode);
      Параметр «hProcess» идентифицирует описатель завершаемого процесса, а в параметре «uExitCode» возвращается код завершения процесса.
      Пользуйтесь «TerminateProcess» лишь в том случае, когда иным способом завершить процесс не удается. Процесс не получает абсолютно никаких уведомлений о том, что он завершается, и приложение не может ни выполнить очистку, ни предотвратить свое неожиданное завершение (если оно, конечно, не использует механизмы защиты). При этом теряются все данные, которые процесс не успел переписать из памяти на диск.
      Для проверки завершения процесса, можно проверить свойство «HasExited», из класса «System.Diagnostics.Process».
      Создайте проект «Windows Form» в «Microsoft Visual Studio» и добавьте на главную форму вашего проекта элементы управления «comboBox» и «button». Первый будет отвечать за вывод списка имен запущенных в данный момент процессов, а второй выполнять вызов метода закрытия выбранного процесса. У вас получится приведенный ниже пример.

      Сделайте двойной клик левой клавишей мыши по любому свободному месту главной формы, вы перейдете в редактор кода с установкой курсора в автоматически созданном методе «Form1_Load», события «Load», выполняющегося при загрузке формы. Вставьте в тело данного метода приведенный ниже код, вызова метода получения списка имен, запущенных процессов.
ProcessList();
Так же добавьте приведённый ниже код самого метода «ProcessList».
private void ProcessList()
{
    //Получаем массив типа System.Diagnostics.Process,
    //предоставляющий данные обо всех процессах,
    //выполняющегося на локальном компьютере.
    System.Diagnostics.Process[] processlist =
        System.Diagnostics.Process.GetProcesses();
    //Выполняем поиск всех процессов в полученном массиве
    //и добавляем их имена в элемент управления comboBox1.
    foreach(System.Diagnostics.Process theprocess in processlist)
    {
        //Добавляем имя текущего процесса
        //в элемент управления comboBox1.
        comboBox1.Items.Add(theprocess.ProcessName);
    }
}
      Перейдите в конструктор главной формы и сделайте двойной клик левой клавишей мыши по элементу управления «button1». Вы перейдете в редактор кода с автоматической установкой курсора в созданном методе «button1_Click», события «Click», возникающего при нажатии на кнопку. Добавьте приведенный ниже листинг, реализующий вызов функции «TerminateProcess».
//Проходимся по всем процессам локального компьютера.
foreach (System.Diagnostics.Process clsProcess in
                   System.Diagnostics.Process.GetProcesses())
{
    //Определяем, совпадает ли начало имени процесса с указанным.
    //Если да, то метод "StartsWith" возвращает значение true
    //и вызывается метод удаления процесса,
    //в противном случае — значение false и происходит
    //переход к следующему процессу.
    if (clsProcess.ProcessName.StartsWith(comboBox1.Text))
    {                    
        TerminateProcess((IntPtr)clsProcess.Id);

        if (clsProcess.HasExited)
            MessageBox.Show("Процесс успешно завершён!", "Завершение процесса",
                   MessageBoxButtons.OK, MessageBoxIcon.Information);
        else
            MessageBox.Show("Ошибка при завершении процесса.", "Завершение процесса",
                   MessageBoxButtons.OK, MessageBoxIcon.Error);                    
    }
}
Так же добавьте приведенный ниже листинг загрузки и вызова API функций.
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, IntPtr dwProcessId);

[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);

[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
static extern bool TerminateProcess(int hProcess, uint uExitCode);

const uint PROCESS_TERMINATE = 0x1;

private void TerminateProcess(IntPtr PID)
{
    IntPtr hProcess = OpenProcess(PROCESS_TERMINATE, false, PID);

    if (hProcess == IntPtr.Zero)
        throw new Win32Exception(
            System.Runtime.InteropServices.Marshal.GetLastWin32Error());

    if (!TerminateProcess((int)hProcess, 0))
        throw new Win32Exception(
            System.Runtime.InteropServices.Marshal.GetLastWin32Error());

    CloseHandle(hProcess);
}
      Запустите проект, нажав на клавишу «F5». После успешной компиляции и запуска вашего проекта у вас откроется главная форма проекта с заполненным списком имен запущенных в данный момент процессов. Выберете из выпадающего списка, имя процесса, завершение работы которого вы хотите выполнить и нажмите на кнопку «Завершить». В случае если программе удастся или нет выполнить завершение, вы получите сообщение с соответствующей информацией.

Комментариев нет:

Отправить комментарий

Большая просьба, не писать в комментариях всякую ерунду не по теме!