進程有啟動就有終止,通過CreateProcess函數可以啟動一個新的子進程,但是如何終結子進程呢?主要有四種方法:
通過主線程的入口函數(main函數、WinMain函數)的return關鍵字終止進程
一個應用程序只有一個入口函數,對于控制臺來說是main函數,對于GUI程序來說這個入口函數一般是WinMain。入口函數通過return關鍵字返回或者程序自上而下執行完成之后,進程可以自動終止,進程相關的所有資源都會被操作清理。這也是開發中最常用的進程終止方法,也是強烈推薦大家使用的終止進程的方式。
那么如何能獲取到子進程的返回值呢,以下面代碼為例,這是一個最簡單的控制臺程序,它返回-3。
#include <iostream>
#include <Windows.h>
int main()
{
return -3;
}
首先演示在cmd控制臺或者bat腳本中如何獲取該進程的最終返回值:通過echo %errorlevel%
命令可以獲取到上一個cmd命令的返回值。如下:
在程序中獲取子進程的返回值,CreateProcess函數創建子進程成功之后,主進程可以拿到子進程的句柄。通過調用GetExitCodeProcess
函數可以獲取到某個進程的返回值,函數原型如下:
BOOL GetExitCodeProcess(
HANDLE hProcess,//子進程句柄
LPDWORD lpExitCode//用于接受子進程的返回值
);
請看以下代碼:
#include <iostream>
#include <Windows.h>
int main()
{
//即將啟動的exe程序路徑
LPCWSTR lpApplicationName = L"D:\\project\\ConsoleApp1\\x64\\Debug\\NewApp.exe";
// 定義啟動信息和進程信息結構
STARTUPINFOW si;
PROCESS_INFORMATION pi;
// 初始化啟動信息結構
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
BOOL ret = CreateProcess(lpApplicationName,
NULL,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);
// 等待進程結束
WaitForSingleObject(pi.hProcess, INFINITE);
// 獲取子進程的返回值
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
// 將無符號整數轉換為有符號整數
int signedExitCode = static_cast<int>(exitCode);
std::cout << "Child process exited with code: " << signedExitCode << std::endl;
return0;
}
主程序在創建子進程之后,首先調用WaitForSingleObject
等待子進程結果,然后調用GetExitCodeProcess
函數獲取子進程的返回值。但是這里注意,如果子進程返回0或者正數是沒問題的,因為DWORD
是一個無符號的整數類型,但是如果子進程返回負數的話,就需要我們手動將無符號整數轉換為有符號整數。最后執行結果如下,可以看到正常獲取到了子進程的返回值。
通過ExitProcess函數終止進程
ExitProcess
函數可以終止進程,并且會設置一個進程的返回值。該函數原型只有一個參數,就是進程的返回值:
void ExitProcess(
UINT uExitCode //進程返回值
);
注意:調用ExitProcess
之后,進程會直接退出,ExitProcess
之后的函數都不會繼續執行,在程序中,一定要盡量避免直接調用這個函數,我們以下面的代碼為例:
#include <iostream>
#include <Windows.h>
int main(int argc, char** argv)
{
ExitProcess(-4);
std::cout << "Hello World!" << std::endl;
return -3;
}
當我們雙擊編譯好的控制臺程序之后,會發現hello World!
并沒有被執行,并且成功的返回了-4,效果如下:
通過TerminateProcess函數終止進程
我們首先來修改子進程程序,通過一個無限while循環使進程永遠不會退出:
#include <iostream>
#include <Windows.h>
int main(int argc, char** argv)
{
while (true) {
std::cout << "Hello World!" << std::endl;
Sleep(1000);
}
}
然后按照上面的代碼,創建完子進程之后,我們可以調用TerminateProcess
函數直接終止子進程。
BOOL ret = CreateProcess(lpApplicationName,
NULL,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);
TerminateProcess(pi.hProcess, -3);
TerminateProcess
函數非常的簡單粗暴,會強制將子進程終結,也應該盡量避免直接調用該函數終止進程,只有在其他辦法都無法強制終結子進程的情況下,才可以使用該函數強制終結進程。
閱讀原文:原文鏈接
該文章在 2025/3/28 11:31:11 編輯過