如何终止由CreateProcess()创建的进程?

24

我使用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)

我如何获取该特定进程的句柄和进程ID?最终如何使用它来关闭该进程?
谢谢。


当您启动 dbntsrv.exe 时,会打开哪个窗口?它是控制台窗口吗? - hmjd
它实际上不像Oracle 10g或cmd那样是一个控制台窗口。您无法在其中进行输入/输出。它只是一个在服务器启动时打开的窗口。 - digvijay
4个回答

17
在结构体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函数检索线程的退出值。


12

PROCESS_INFORMATION 结构体中,变量 pi 返回了进程的句柄。

TerminateProcess() 函数可用于终止进程。但是,您应该考虑为什么需要终止进程以及为什么无法进行优雅的关闭。

注意,在调用 CreateProcess() 之前,您需要设置 sicb 成员:

si.cb = sizeof(STARTUPINFO);

编辑:

为了抑制控制台窗口,请在CreateProcess()调用中将创建标志(第六个参数)指定为CREATE_NO_WINDOW

编辑(2):

为了抑制窗口,请在调用CreateProcess()之前设置以下STARTUPINFO结构的成员:

STARTUPINFO si = {0};
si.cb          = sizeof(STARTUPINFO);
si.dwFlags     = STARTF_USESHOWWINDOW;
si.wShowWindow = FALSE;

1
优雅关闭加1。可以通过向进程发送消息等方式指示进程关闭。 - Alexey Frunze

9

优雅地关闭进程

为了优雅地关闭进程,您应该首先发送一个关闭信号:

Win32中如何“优雅”终止应用程序。

如果您绝对必须关闭一个进程,请按照以下步骤操作:
1. 向您想要关闭的进程拥有的所有顶级窗口发送 WM_CLOSE。许多 Windows 应用程序会响应此消息并关闭。
注意:控制台应用程序对 WM_CLOSE 的响应取决于它是否安装了控制处理程序。
2. 使用 EnumWindows() 查找您目标窗口的句柄。在回调函数中,检查窗口的进程 ID 是否与您想要关闭的进程匹配。您可以通过调用 GetWindowThreadProcessId() 来实现这一点。一旦建立了匹配,使用 PostMessage() 或 SendMessageTimeout() 将 WM_CLOSE 消息发布到窗口。
3. 使用 WaitForSingleObject() 等待进程的句柄。确保您使用超时值等待,因为有许多情况下 WM_CLOSE 无法关闭应用程序。请记住,要使超时足够长(使用 WaitForSingleObject() 或 SendMessageTimeout()),以便用户可以响应响应 WM_CLOSE 消息创建的任何对话框。
4. 如果返回值是 WAIT_OBJECT_0,则应用程序已干净地关闭自身。如果返回值是 WAIT_TIMEOUT,则必须使用 TerminateProcess() 关闭应用程序。
注意:如果您从 WaitForSingleObject() 中获得的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,请使用 GetLastError() 确定原因。
遵循这些步骤,您可以为应用程序提供最好的关闭机会(除了 IPC 或用户干预)。

请参考此答案的代码。

终止进程

如果您不关心干净的关闭,可以使用TerminateProcess()。但是,请注意TerminateProcess()是异步的;它启动终止并立即返回。如果您必须确保进程已终止,请使用指向该进程的句柄调用WaitForSingleObject()函数。

注意:访问权限需要PROCESS_TERMINATESYNCHRONIZE

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

这个问题在MSDN中有详细的解释:

如果结果是非零的(也就是成功了),你将会在pi结构体中得到句柄和进程ID。

为了结束进程,你可以使用TerminateProcess


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接