Как прекратить процесс, созданный CreateProcess ()? - PullRequest
16 голосов
/ 24 февраля 2012

Я создал процесс, используя CreateProcess().Это код:

STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
result = CreateProcess("C:\\AP\\DatabaseBase\\dbntsrv.exe", NULL, NULL, NULL, FALSE, 0, NULL, "C:\\ADP\\SQLBase", &si, &pi)

Как я могу получить Handle и processId этого конкретного процесса?И в конечном итоге использовать его, чтобы закрыть этот процесс?
Спасибо.

Ответы [ 5 ]

11 голосов
/ 24 февраля 2012

В структуре pi вы получите:

typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess;
    HANDLE hThread;
    DWORD  dwProcessId;
    DWORD  dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

Первый параметр - это дескриптор процесса.

Этот дескриптор можно использовать для завершения процесса:

BOOL WINAPI TerminateProcess(
    __in  HANDLE hProcess,
    __in  UINT uExitCode
);

hProcess [in]
Дескриптор завершаемого процесса.

Дескриптор должен иметь право доступа PROCESS_TERMINATE.Дополнительные сведения см. В разделе «Безопасность процессов и права доступа».

uExitCode [in]
Код выхода, который должен использоваться процессом, и потоки завершаются в результате этого вызова.Используйте функцию GetExitCodeProcess, чтобы получить значение выхода процесса.Используйте функцию GetExitCodeThread, чтобы получить выходное значение потока.

11 голосов
/ 24 февраля 2012

Дескриптор процесса возвращается в структуре PROCESS_INFORMATION , переменной pi.

Функция TerminateProcess () может использоваться для завершения процесса. Однако вам следует подумать, почему вам нужно завершить процесс и почему постепенное отключение невозможно.

Обратите внимание, что вам нужно установить cb член si перед вызовом CreateProcess():

si.cb = sizeof(STARTUPINFO);

EDIT:

Чтобы подавить окно консоли, укажите CREATE_NO_WINDOW в качестве флага создания (шестой аргумент) в вызове CreateProcess().

РЕДАКТИРОВАТЬ (2):

Чтобы закрыть окно, попробуйте установить следующие элементы структуры STARTUPINFO перед вызовом CreateProcess():

STARTUPINFO si = {0};
si.cb          = sizeof(STARTUPINFO);
si.dwFlags     = STARTF_USESHOWWINDOW;
si.wShowWindow = FALSE;
1 голос
/ 03 июля 2018

Чистое завершение процесса

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

Как завершить приложение «Чисто» в Win32.

Если вам абсолютно необходимо остановить процесс, выполните следующие действия:

  1. Разместите WM_CLOSE во всех окнах верхнего уровня, принадлежащих процессу, который вы хотите завершить. Многие приложения Windows отвечают на это сообщение выключением.

    ПРИМЕЧАНИЕ. Ответ консольного приложения на WM_CLOSE зависит от того, установлен ли на нем обработчик элемента управления.

    Используйте EnumWindows (), чтобы найти дескрипторы ваших окон назначения. В вашей функции обратного вызова проверьте, соответствует ли идентификатор процесса Windows процессу, который вы хотите завершить. Вы можете сделать это, вызвав GetWindowThreadProcessId (). Как только вы установили совпадение, используйте PostMessage () или SendMessageTimeout (), чтобы отправить сообщение WM_CLOSE в окно.

  2. Используйте WaitForSingleObject () для ожидания дескриптора процесса. Обязательно дождитесь значения тайм-аута, поскольку во многих ситуациях WM_CLOSE не закрывает приложение. Не забудьте сократить время ожидания (либо с помощью WaitForSingleObject (), либо с помощью SendMessageTimeout ()), чтобы пользователь мог отвечать на любые диалоговые окна, созданные в ответ на сообщение WM_CLOSE.

  3. Если возвращаемое значение - WAIT_OBJECT_0, то приложение полностью закрылось. Если возвращаемое значение WAIT_TIMEOUT, то вы должны использовать TerminateProcess (), чтобы закрыть приложение.

    ПРИМЕЧАНИЕ. Если вы получаете возвращаемое значение из WaitForSingleObject (), отличного от WAIT_OBJECT_0 или WAIT_TIMEOUT, используйте GetLastError () для определения причины.

Выполняя эти шаги, вы даете приложению наилучшую возможность аккуратно завершить работу (кроме IPC или вмешательства пользователя).

См. Этот ответ для кода.

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

Если вы не заботитесь о чистом отключении, вы можете использовать TerminateProcess(). Тем не менее, важно отметить, что TerminateProcess() является асинхронным; он инициирует прекращение и немедленно возвращается. Если вам необходимо убедиться, что процесс завершен, вызовите функцию WaitForSingleObject() с дескриптором процесса.

TerminateProcess(pi.hProcess, 0);

// 500 ms timeout; use INFINITE for no timeout
const DWORD result = WaitForSingleObject(pi.hProcess, 500);
if (result == WAIT_OBJECT_0) {
    // Success
}
else {
    // Timed out or an error occurred
}

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

Не закрывается, просто подождите, пока закончите

Если процесс завершится сам по себе, вместо завершения вы можете подождать, пока он не завершится.

WaitForSingleObject(pi.hProcess, INFINITE);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
1 голос
/ 24 февраля 2012
STARTUPINFOA siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);

DWORD dwExitCode = 0;
if (CreateProcess(prgName.c_str(),
                (LPSTR) parameters.c_str(), 
                0, 
                0, 
                false,
                CREATE_DEFAULT_ERROR_MODE, 
                0, 
                0,
                &siStartupInfo, 
                &piProcessInfo) != false)
{       
    dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, (time_in_ms));
}
else
{        
    return GetLastError(); //return error or do smething else
}

CloseHandle(piProcessInfo.hProcess);
CloseHandle(piProcessInfo.hThread);

piProcessInfo.hProcess - дескриптор процесса.

WaitForSingleObject: ждет, пока указанный объект находится в сигнальном состоянии или пока не истечет интервал времени ожидания.

После этого (time_in_ms) процесс будет закрыт.

1 голос
/ 24 февраля 2012

Это подробно объясняется в MSDN :

Если результат не равен нулю (что означает, что он успешен), вы получите дескриптор и processid в piструктура .

Чтобы убить процесс, вы можете использовать TerminateProcess

...