【问题标题】:how to terminate a process created by CreateProcess()?如何终止由 CreateProcess() 创建的进程?
【发布时间】:2012-03-14 18:25:33
【问题描述】:

我使用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?并最终用它来关闭这个进程?
谢谢。

【问题讨论】:

  • 启动dbntsrv.exe时会打开什么窗口?是控制台窗口吗?
  • 它实际上并不是像 oracle 10g 或 cmd 这样的控制台窗口。你不能在上面输入/输出。只是服务器启动时打开的一个窗口

标签: c++ winapi visual-c++ mfc createprocess


【解决方案1】:

在结构体pi 中你会得到:

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

第一个参数是进程的句柄。

You can use that handle to end the process:

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

hProcess [in]
要终止的进程的句柄。

句柄必须具有 PROCESS_TERMINATE 访问权限。有关详细信息,请参阅进程安全性和访问权限。

uExitCode [in]
由于此调用,进程和线程要使用的退出代码终止。使用 GetExitCodeProcess 函数检索进程的退出值。使用 GetExitCodeThread 函数检索线程的退出值。

【讨论】:

    【解决方案2】:

    进程句柄在PROCESS_INFORMATION 结构pi 变量中返回。

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

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

    si.cb = sizeof(STARTUPINFO);
    

    编辑:

    要抑制控制台窗口,请指定CREATE_NO_WINDOW,作为CreateProcess() 调用中的creation flag(第六个参数)。

    编辑(2):

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

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

    【讨论】:

    • +1 用于正常关机。该过程可以通过例如指示关闭。向它发送消息。
    【解决方案3】:

    干净地关闭进程

    要干净地关闭进程,你应该先发送一个关闭信号:

    How To Terminate an Application "Cleanly" in Win32.

    如果您绝对必须关闭某个进程,请按照以下步骤操作:

    1. 将 WM_CLOSE 发布到您要关闭的进程所拥有的所有顶级窗口。许多 Windows 应用程序通过关闭来响应此消息。

    注意:控制台应用程序对 WM_CLOSE 的响应取决于它是否安装了控制处理程序。

    使用 EnumWindows() 查找目标窗口的句柄。在您的回调函数中,检查 Windows 的进程 ID 是否与您要关闭的进程匹配。您可以通过调用 GetWindowThreadProcessId() 来执行此操作。建立匹配后,使用 PostMessage() 或 SendMessageTimeout() 将 WM_CLOSE 消息发布到窗口。

    1. 使用 WaitForSingleObject() 来等待进程的句柄。确保使用超时值等待,因为在很多情况下 WM_CLOSE 不会关闭应用程序。请记住使超时时间足够长(使用 WaitForSingleObject() 或使用 SendMessageTimeout()),以便用户可以响应为响应 WM_CLOSE 消息而创建的任何对话框。

    2. 如果返回值为 WAIT_OBJECT_0,则应用程序完全关闭了自己。如果返回值为 WAIT_TIMEOUT,则必须使用 TerminateProcess() 关闭应用程序。

    注意:如果您从 WaitForSingleObject() 获得的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,请使用 GetLastError() 来确定原因。

    通过执行这些步骤,您可以让应用程序有最好的机会彻底关闭(IPC 或用户干预除外)。

    See this answer for code.

    终止进程

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

    注意:Access rights 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);
    

    【讨论】:

      【解决方案4】:

      这在MSDN中有详细解释:

      如果结果不为零(这意味着它成功),您将在pi structure 中获得句柄和进程ID。

      为了杀死进程你可以使用TerminateProcess

      【讨论】:

        猜你喜欢
        • 2018-12-21
        • 2017-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-30
        • 1970-01-01
        • 2015-03-12
        • 1970-01-01
        相关资源
        最近更新 更多