首页 > 解决方案 > 检查进程是否在 Windows C++ 中运行的最佳方法

问题描述

(为简洁、清晰和实用而编辑)

我的程序 (B) 监视另一个不是我自己的程序 (A)。我想检测该程序何时退出或崩溃。我对源代码的访问是有限的,我更喜欢不需要我对所观看程序的源代码进行更改的解决方案,但如果它是一个更好的解决方案,我可以进行这些更改。从最好到最坏的方法:(对修正/改进感兴趣)

1) CreateToolhelp32Snapshot() + Process32Next()循环遍历具有 pid (:: th32ProcessID ) 和 name (:: szExeFile ) 元素的PROCESSENTRY32结构。Process32Next() 返回的 Foreach PROCESSENTRY32 结构检查 szExeFile 元素是否与进程名称匹配。

当或如果找到匹配项,则可以使用 .th32ProcessID 调用OpenProcess()并使用返回的进程句柄调用WaitForSingleObject (hprocess,0) ,但是如果 szExeFile 与您的文件名匹配,则该进程仍在运行,因此其余的可能是不必要的,但是也许 WaitForSingleObject() 会更快地检查循环。

2) EnumProcesses()获取 PID 数组。然后 foreach PID 元素调用OpenProcess()来获取进程句柄并使用该句柄调用GetProcessImageFilename()然后CloseHandle()来关闭进程。一旦你有正确的 PID 调用 OpenProcess() 来获取进程句柄,然后调用WaitForSingleObject()。比 CreateToolhelp32Snapshot() 方法需要循环和更多步骤。

3)GetCurrentProcessId()+ IPC。需要更改进程 A 中的代码,这可能是不可能的或不可取的。这种方法看起来有点复杂和丑陋,但至少没有循环。A 中的 3 行和 B 中的 4 行,或者如果您不计算 OpenProcess 调用,则可能只有 2 行。我猜没那么糟糕。事实上,我想我现在要尝试这种方法。

问题是进程间通信是一个皮塔饼。也许比必须遍历循环更糟糕。如果 IPC 更容易/更简单或不需要,这可能是最好的方法。对此的变体可能会使用GetCurrentProcess()DuplicateHandle()来获取进程句柄,然后将该句柄存储为共享内存对象。
过程一:

HANDLE hpidA = CreateFileMappingA(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 4, "pidobj");
int * ppidA = reinterpret_cast<int *>(MapViewOfFile(hpidA, FILE_MAP_WRITE, 0, 0, 4));
*ppidA = GetCurrentProcessId();

过程乙:

HANDLE hpidB = OpenFileMappingA(FILE_MAP_READ, 0, "pidobj");
int * ppidB = reinterpret_cast<int *>(MapViewOfFile(hpidB, FILE_MAP_READ, 0, 0, 4));
HANDLE hproc = OpenProcess(SYNCHRONIZE, FALSE, *ppidB);
bool running = WaitForSingleObject(hproc, 0);

4)System("tasklist /fi "imagename eq vlc.exe" /fo csv /nh > proc.txt")然后读取文件以获取 PID,然后 OpenProcess() + WaitForSingleObject() 可能也可以工作,但它是一个缓慢、丑陋和不优雅的解决方案,会导致磁盘访问。

注意:在类似的问题中有一些关于 PID 回收问题的讨论,这些问题与使用 OpenProcess() 本身检查进程是否正在运行有关,但似乎 PID 不会被回收,直到/除非你调用了 CloseHandle()

这是我之前想做的:

System("for /f \"delims=, tokens=2\" %g in (\'tasklist /fi \"imagename eq vlc.exe\" /fo csv /nh\') do set proc=%g");
int nchars = GetEnvironmentVariableA("proc", procidstr, 16);

然后是这样的:

for (int i = nchars; i; i--) procidstr[i] = procidstr[i+1]; //strip ""
int procid = strtol(procidstr, 0, 0);
HANDLE hproc = OpenProcess(SYNCHRONIZE, FALSE, procid);
int running = WaitForSingleObject(hproc, 0);

这确实将环境变量“proc”设置为 PID,但 GetEnvironmentVariable() 仅返回“\0”。我也尝试了 setx ,结果相同。它在控制台中设置了变量,但由于我假设的范围问题,GetEnvironmentVariable() 无法检索它。这让我想知道是否有任何方法可以设置环境变量并在 c-c++ 程序中实际使用它。我想我会就此提出一个单独的问题。

标签: c++cwindowsinterprocesstasklist

解决方案


推荐阅读