You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何高效持续检测指定进程是否运行?

高效检测指定进程运行状态的优化方案

一、低成本即时优化

  • 降低检测频率:4ms的检测间隔完全超出实际需求,进程启动/退出属于毫秒级以上的操作,将间隔调整为500ms~1秒,能直接大幅减少系统调用次数,CPU波动问题会立刻缓解。
  • 优化快照遍历逻辑:你的原代码会遍历所有进程,找到目标进程后未提前终止循环。可以在找到两个目标进程后直接跳出循环,减少不必要的遍历:
void inline isProcessRunning() {
    PROCESSENTRY32 entry{};
    entry.dwSize = sizeof(PROCESSENTRY32);

    bool foundApp1 = false, foundApp2 = false;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (Process32First(snapshot, &entry)) {
        do {
            if (!wcsicmp(entry.szExeFile, L"App1.exe")) {
                // Do something...
                foundApp1 = true;
            }
            if (!wcsicmp(entry.szExeFile, L"App2.exe")) {
                // do something...
                foundApp2 = true;
            }
            // 找到两个目标进程后提前退出循环
            if (foundApp1 && foundApp2) break;
        } while (Process32Next(snapshot, &entry));
    }
    CloseHandle(snapshot);
}

二、无轮询的高效方案:WMI事件订阅

通过订阅Windows管理规范(WMI)的进程创建/删除事件,让系统在目标进程状态变化时主动通知程序,彻底避免定时轮询的开销。核心思路是注册进程创建/销毁的监控事件,仅在事件触发时处理逻辑。

示例代码框架:

#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

// 事件回调函数,处理进程状态变化
HRESULT CALLBACK ProcessEventSink(IWbemObjectSink *pSink, IWbemClassObject *pObj, LONG lFlags) {
    VARIANT varName;
    HRESULT hr = pObj->Get(L"ProcessName", 0, &varName, NULL, NULL);
    if (SUCCEEDED(hr)) {
        if (!wcsicmp(varName.bstrVal, L"App1.exe")) {
            // App1启动/退出的处理逻辑
        } else if (!wcsicmp(varName.bstrVal, L"App2.exe")) {
            // App2启动/退出的处理逻辑
        }
        VariantClear(&varName);
    }
    return WBEM_S_NO_ERROR;
}

// 初始化WMI订阅
void SetupWmiProcessMonitoring() {
    IWbemLocator *pLoc = NULL;
    IWbemServices *pSvc = NULL;
    IWbemObjectSink *pSink = NULL;

    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);

    CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);
    pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);

    // 创建事件接收器
    CoCreateInstance(CLSID_EventSink, 0, CLSCTX_INPROC_SERVER, IID_IWbemObjectSink, (LPVOID *)&pSink);

    // 订阅进程创建事件
    BSTR query = SysAllocString(L"SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'");
    pSvc->ExecNotificationQueryAsync(_bstr_t(L"WQL"), query, WBEM_FLAG_SEND_STATUS, NULL, pSink);

    // 订阅进程退出事件
    query = SysAllocString(L"SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'");
    pSvc->ExecNotificationQueryAsync(_bstr_t(L"WQL"), query, WBEM_FLAG_SEND_STATUS, NULL, pSink);

    // 保持线程运行以接收事件
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        DispatchMessage(&msg);
    }

    // 清理资源(实际代码中需根据业务逻辑合理处理)
    pSink->Cancel();
    pSvc->Release();
    pLoc->Release();
    pSink->Release();
    CoUninitialize();
}

三、基于PID缓存的轻量检测

如果不想引入WMI,可以缓存目标进程的PID,通过OpenProcess和GetExitCodeProcess快速检测进程存活状态,仅在PID失效时(比如进程退出后PID被复用)才重新创建快照扫描最新PID:

DWORD g_app1PID = 0, g_app2PID = 0;

// 检测指定PID的进程是否存活
bool isPIDAlive(DWORD pid) {
    if (pid == 0) return false;
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
    if (hProcess == NULL) return false;
    DWORD exitCode;
    GetExitCodeProcess(hProcess, &exitCode);
    CloseHandle(hProcess);
    return exitCode == STILL_ACTIVE;
}

// 扫描进程快照,更新目标进程的PID
void updateProcessPIDs() {
    PROCESSENTRY32 entry{};
    entry.dwSize = sizeof(PROCESSENTRY32);
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (Process32First(snapshot, &entry)) {
        do {
            if (!wcsicmp(entry.szExeFile, L"App1.exe")) {
                g_app1PID = entry.th32ProcessID;
            }
            if (!wcsicmp(entry.szExeFile, L"App2.exe")) {
                g_app2PID = entry.th32ProcessID;
            }
        } while (Process32Next(snapshot, &entry));
    }
    CloseHandle(snapshot);
}

void inline isProcessRunning() {
    bool app1Running = isPIDAlive(g_app1PID);
    bool app2Running = isPIDAlive(g_app2PID);

    // 如果PID检测失败,重新扫描更新PID
    if (!app1Running) {
        updateProcessPIDs();
        app1Running = isPIDAlive(g_app1PID);
    }
    if (!app2Running) {
        updateProcessPIDs();
        app2Running = isPIDAlive(g_app2PID);
    }

    if (app1Running) {
        // Do something...
    }
    if (app2Running) {
        // do something...
    }
}

这种方法的常规检测开销极低,只有当PID失效时才会触发快照扫描,能大幅减少系统调用次数。

内容的提问来源于stack exchange,提问作者Denellyne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:00:31