• 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

  • 相关阅读:
    网络流 KM dinic
    网络流 增广路 回退
    树链剖分
    线段树区间更新 lazy
    全排列
    各种蕴含算法思想的DP
    各种蕴含算法思想的DP
    Strassen矩阵乘法之思考
    [0,x)的随机数
    hdu1331 按着题目的公式直接写
  • 原文地址:https://www.cnblogs.com/zhaotianff/p/15884991.html
Copyright © 2020-2023  润新知