如何等待目标进程启动?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)
问题分析与修复
核心问题点
- 无等待逻辑:
getProc仅单次扫描进程列表,未找到目标就直接返回,没有循环等待直到进程启动的逻辑。 - 进程扫描遗漏:
getProc中直接跳过Process32First返回的第一个进程,只遍历Process32Next的结果,可能漏掉目标进程。 - 全局变量滥用:全局的
pe32在未找到目标进程时,会保留扫描到的最后一个进程的信息,导致后续pID错误指向其他进程。 get函数逻辑混乱:函数参数是目标PID,但内部循环扫描所有进程时,每次都用传入的PID调用OpenProcess,且错误判断ac_cube.exe(并非目标进程),最终返回的句柄大概率无效或指向错误进程。- 缺失错误处理:未处理
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
相关产品推荐
相关产品推荐

