Windows編程系列:如何監測某個進程是否退出?


使用WaitForSingleObject函數,可以判斷進程是否退出。

WaitForSingleObject函數的作用是:等待直到指定的對象處於信號狀態(通知狀態)或到達指定的等待時間(超時時間)。

函數聲明如下:

1 DWORD WaitForSingleObject(
2   [in] HANDLE hHandle,
3   [in] DWORD  dwMilliseconds
4 );

參數說明:

hHandle:需要等待的對象

dwMilliseconds:超時時間(毫秒),如果設置為INFINITE,則會一直等待下去,直到對象被通知。

 

WaitForSingleObject支持以下對象:

  • Change notification
  • Console input
  • Event
  • Memory resource notification
  • Mutex
  • Process
  • Semaphore
  • Thread
  • Waitable timer

這里只是簡單介紹一下這個函數,如果需要了解更詳細的說明,可以參考:https://docs.microsoft.com/zh-cn/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject

 

監控新創建的進程退出:

這里我們創建一個MFC程序來進行演示,在界面上添加一個按鈕,創建記事本進程。

創建進程后創建一個線程等待進程退出,在線程處理函數中調用WaitForSingleObject,傳入進程對象進行等待

1 void CProcessMonitorDlg::OnBnClickedButton2()
2 {
3     LPTSTR szNotepad = _tcsdup(TEXT("notepad.exe"));
4     ::CreateProcess(NULL, szNotepad, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pi);
5     ::CreateThread(NULL, 0, MonitorThreadProc, NULL, 0, NULL);    
6     free(szNotepad);
7 }

線程處理函數

 1 DWORD __stdcall CProcessMonitorDlg::MonitorThreadProc(LPVOID lpThreadParameter)
 2 {
 3     ::WaitForSingleObject(pi.hProcess, INFINITE);
 4     DWORD dwCode = 0;
 5     GetExitCodeProcess(pi.hProcess, &dwCode);
 6     TCHAR buf[260]{};
 7     wsprintf(buf, L"notepad.exe exit,exit code = %d", dwCode);
 8     ::MessageBox(NULL, buf, L"tooltip", MB_OK);
 9     return 0;
10 }

 

詳細的代碼可以參考文末的示例代碼。

 

監控已經存在的進程退出:

我們先調用CreateToolhelp32Snapshot、Process32First和Process32Next函數進行進程的枚舉,然后再調用WaitForSingleObject等待進程退出。

這里我們以cmd.exe為例

先枚舉進程,然后創建線程,等待進程退出。

 1 PROCESSENTRY32 pe{};
 2     pe.dwSize = sizeof(PROCESSENTRY32);
 3     HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 4 
 5     if (hSnapShot == NULL)
 6     {
 7         ::MessageBox(NULL, L"創建進程快照失敗", L"", MB_OK | MB_ICONINFORMATION);
 8         return;
 9     }
10 
11     BOOL bNext = Process32First(hSnapShot, &pe);
12 
13     while (bNext)
14     {
15         if (lstrcmp(pe.szExeFile,L"cmd.exe") == 0)
16         {
17             ::CreateThread(NULL, 0, MonitorCMDThreadProc, (PVOID)pe.th32ProcessID, 0, NULL);
18             CloseHandle(hSnapShot);
19             break;
20         }
21 
22         bNext = Process32Next(hSnapShot, &pe);
23     }
24 
25 
26     CloseHandle(hSnapShot);

 

線程處理函數

 1 DWORD dwCmdPid = (DWORD)lpThreadParameter;
 2     HANDLE hProcessCmd =::OpenProcess(PROCESS_QUERY_INFORMATION| SYNCHRONIZE, FALSE, dwCmdPid);
 3 
 4     if(hProcessCmd)
 5         ::WaitForSingleObject(hProcessCmd, INFINITE);
 6 
 7     DWORD dwCode = 0;
 8     GetExitCodeProcess(hProcessCmd, &dwCode);
 9     CloseHandle(hProcessCmd);
10     TCHAR buf[260]{};
11     wsprintf(buf, L"cmd.exe exit,exit code = %d", dwCode);
12     ::MessageBox(NULL, buf, L"tooltip", MB_OK);
13     return 0;

 

 

其實這種方式挺簡單的,可以不用開線程一直去刷,然后判斷進程是否存在。

通過這種方式可以監測服務程序意外退出,並進行重啟操作。

 

示例代碼

https://github.com/zhaotianff/WindowsProgramming/tree/master/ProcessMonitor


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM