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