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

如何等待目标进程启动?C++进程检测代码问题求助

问题描述

开发环境:Visual Studio 2022,ISO C++20标准,多字节字符集
需求:实现等待目标进程ac_client.exe启动后再执行后续内存读写操作的逻辑
现象:

  • 目标进程提前启动时,代码可正常运行
  • 目标进程未启动时,等待逻辑失效,循环检测几次后错误关联其他进程,直接进入后续内存读写流程(读写功能本身无问题)

原代码实现:

PROCESSENTRY32 pe32;
HANDLE openProc;
std::string choice("ac_client.exe");

DWORD getProc(std::string name)
{
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    pe32.dwSize = sizeof(pe32);
    Process32First(snap, &pe32);
    while (Process32Next(snap, &pe32))
    {
        if (!name.compare(pe32.szExeFile))
        {
            openProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
            CloseHandle(snap);
            return 0;
        }
    }
}

HANDLE get(DWORD pID)
{
    bool endFunction{ false };
    HANDLE procCheck{};
    HANDLE snap(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
    Process32First(snap, &pe32);
    while (Process32Next(snap, &pe32))
    {
        procCheck = OpenProcess(PROCESS_ALL_ACCESS, false, pID);
        std::cout << pe32.szExeFile << '\n';
        std::cout << choice << '\n';
        if (pe32.szExeFile == "ac_cube.exe")
        {
            if (!choice.compare(pe32.szExeFile) == 0)
            {
                std::cout << pe32.szExeFile << '\n';
                    std::cout << choice << '\n';
                    endFunction = true;
            }
        }
    }
    return procCheck;
}

int main()
{
    
    getProc(choice);

    DWORD pID = pe32.th32ProcessID;

    
    HANDLE pHandle = get(pID);
}

控制台输出片段:

VsDebugConsole.exe
ac_client.exe
conhost.exe
ac_client.exe
assaultCubeC.exe //this is the program im trying to fix if it matters
ac_client.exe
SearchFilterHost.exe
ac_client.exe
msvsmon.exe
ac_client.exe
SUCCESSFULLY LOADED || DETAILS BELOW

Health       -> 236
AR Ammo      -> 320 (284)
Pistol Ammo  -> 300 (264)

问题分析与修复

核心问题点

  1. 无等待逻辑:getProc仅单次扫描进程列表,未找到目标就直接返回,没有循环等待直到进程启动的逻辑。
  2. 进程扫描遗漏:getProc中直接跳过Process32First返回的第一个进程,只遍历Process32Next的结果,可能漏掉目标进程。
  3. 全局变量滥用:全局的pe32在未找到目标进程时,会保留扫描到的最后一个进程的信息,导致后续pID错误指向其他进程。
  4. get函数逻辑混乱:函数参数是目标PID,但内部循环扫描所有进程时,每次都用传入的PID调用OpenProcess,且错误判断ac_cube.exe(并非目标进程),最终返回的句柄大概率无效或指向错误进程。
  5. 缺失错误处理:未处理CreateToolhelp32Snapshot、OpenProcess等API的调用失败情况,导致异常场景下逻辑失控。

修复后的实现代码

替换原有的getProc和get函数,实现正确的等待逻辑:

#include <windows.h>
#include <tlhelp32.h>
#include <string>
#include <iostream>
#include <chrono>
#include <thread>

// 等待目标进程启动并返回其进程句柄
HANDLE WaitForProcess(const std::string& processName, DWORD waitIntervalMs = 500)
{
    while (true)
    {
        HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (snap == INVALID_HANDLE_VALUE)
        {
            std::cerr << "CreateToolhelp32Snapshot failed: " << GetLastError() << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(waitIntervalMs));
            continue;
        }

        PROCESSENTRY32 pe32{};
        pe32.dwSize = sizeof(PROCESSENTRY32);

        // 遍历所有进程,包括第一个进程
        if (Process32First(snap, &pe32))
        {
            do
            {
                if (processName == pe32.szExeFile)
                {
                    // 按需调整权限(PROCESS_ALL_ACCESS权限过高,建议使用最小必要权限)
                    HANDLE procHandle = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pe32.th32ProcessID);
                    CloseHandle(snap);
                    return procHandle;
                }
            } while (Process32Next(snap, &pe32));
        }

        CloseHandle(snap);
        // 未找到进程,等待后重试
        std::cout << "Waiting for " << processName << " to start..." << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(waitIntervalMs));
    }
}

int main()
{
    const std::string targetProcess = "ac_client.exe";
    HANDLE pHandle = WaitForProcess(targetProcess);

    if (pHandle == nullptr)
    {
        std::cerr << "Failed to open target process" << std::endl;
        return 1;
    }

    std::cout << "SUCCESSFULLY LOADED || DETAILS BELOW" << std::endl;
    // 后续内存读写逻辑...

    // 使用完记得关闭句柄
    CloseHandle(pHandle);
    return 0;
}

关键优化说明

  • 循环扫描进程列表,直到找到目标进程,实现真正的等待逻辑
  • 正确遍历所有进程(包括Process32First返回的第一个进程)
  • 避免全局变量,使用局部变量管理进程信息,防止脏数据
  • 添加API调用错误处理,增强鲁棒性
  • 按需调整进程权限(PROCESS_ALL_ACCESS权限过高,建议使用实际需要的最小权限,减少安全风险)
  • 使用C++标准库的std::this_thread::sleep_for实现等待,代码更规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 00:25:19