检查特定进程运行的快速方法

要检查进程是否正在运行,可以使用“CreateToolHelp32SnapShot”Windows API函数并枚举正在运行的进程。 示例C / C ++代码在答案问题中给出: 检查是否有一个特定的进程正在C ++的窗口上运行

我的问题是,如果你知道你正在寻找一个特定的过程,是否有更快的方法来find答案,而不必依次检查每个过程? 我们需要定期检查我们的远程支持工具TeamViewer.exe是否正在运行。 请注意,TeamViewer是由第三方编写的,我们无法控制它或者EXE的内部知识。

编辑:

TeamViewer提供了一些有关其内部过程的信息,可以用来加速这个过程(参见接受的答案)。 答案还显示了如何加速对任何进程的检查(通过保存进程ID)。

你必须采取的第一步涉及枚举进程。 用toolhelp或EnumProcesses执行此EnumProcesses 。 如果你找到你的进程,把PID传给OpenProcess来获得进程句柄。 然后等待进程被发信号。 这样可以避免在最初的枚举之外进行轮询。

如果您的初始枚举未能找到进程,您将不得不重复枚举。 无论使用哪一个toolhelp或EnumProcesses都会更有效率。 也许扼杀投票。 您也可以选择使用WMI来通知新的流程创建,并且完全避免轮询的需要。

经过大量研究(以及TeamViewer支持的回应),我发布了一个明确的答案,希望对其他人有所帮助。 代码是在Delphi中,但可以轻松地转换为C ++。

*如果您没有关于过程的内部信息*

 function IsRemoteSupportRunning() : Boolean; var hSnapShot, hProcess: THandle; process: TProcessEntry32; bFound: Boolean; begin bFound := False; if (cache.dwTeamViewerID = 0) then begin // TeamViewer not running...is it running now? try hSnapShot := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0); process.dwSize := Sizeof(TProcessEntry32); if (Process32First(hSnapShot, process)) then bFound := (AnsiCompareText(REMOTE_SUPPORT_EXE, process.szExeFile) = 0); if (not bFound) then begin while (Process32Next(hSnapShot, process)) do begin bFound := (AnsiCompareText(REMOTE_SUPPORT_EXE, process.szExeFile) = 0); if (bFound) then break; end; end; CloseHandle(hSnapShot); except end; // If found, save the process ID if (bFound) then cache.dwTeamViewerID := process.th32ProcessID; end else begin // In a previous call to this function, TeamViewer was running... hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, cache.dwTeamViewerID); if (hProcess > 0) then begin // Still running! bFound := True; CloseHandle(hProcess); end else begin // Process is no longer running cache.dwTeamViewerID := 0; end; end; Result := bFound; end; 

在我的机器上,如果TeamViewer.exe没有运行,这消耗约1.5ms。 一旦运行并且PID已知,则会下降到〜6.8μs。

*如果您有一些关于或者控制过程的信息*

这里有许多可能性。 例如,该进程可以使用以下代码创建(或编写进程以创建)共享内存对象:

 CreateFileMapping(HWND($FFFFFFFF), nil, PAGE_READONLY, 0, 32, 'MyProcess'); 

您现在可以使用以下命令检查正在运行的进程:

 var hMapping: HWND; hMapping := CreateFileMapping(HWND($FFFFFFFF), nil, PAGE_READONLY, 0, 32, 'MyProcess'); if (hMapping <> 0) then begin if (GetLastError() = ERROR_ALREADY_EXISTS) then bRunning := True; CloseHandle(hMapping); end; 

最后,TeamViewer支持通知我一个指定的互斥体对象,您将在下面的代码中看到该对象。 请注意,这是特定于TeamViewer的,但是如果您对流程有控制权,则可以创建一个互斥体并使用此技术。 在我的系统上,这消耗〜2.6μs!

 function IsRemoteSupportRunning() : Boolean; var hProcess: THandle; begin // Use OpenMutex to see if TeamViewer.exe is running... Result := False; hProcess := OpenMutex(MUTEX_ALL_ACCESS, False, PChar('TeamViewer_Win32_Instance_Mutex')); if (hProcess > 0) then begin bFound := True; CloseHandle(hProcess); end; end; 

TeamViewer通知我一个强大的工具WinObj来调查系统中的对象, https: //technet.microsoft.com/de-de/sysinternals/bb896657.aspx。 查看BaseNamedObjects。 互斥体显示为“突变体”。