检查特定进程是否正在运行的快速方法
Fast way to check for a specific process running
要检查进程是否正在运行,可以使用"CreateToolHelp32SnapShot"Windows API函数并枚举正在运行的进程。示例C/C++代码在回答问题中给出:检查是否有一个特定进程在带有C++的窗口上运行
我的问题是,如果你知道你在寻找一个特定的流程,是否有一种更快的方法可以找到答案,而不必依次检查每个流程?我们需要定期检查我们的远程支持工具TeamViewer.exe是否正在运行。请注意,TeamViewer是由第三方编写的,我们无法控制它,也不知道EXE的内部结构。
编辑:
TeamViewer提供了一些关于其流程内部的信息,这些信息可用于在本例中加快速度(请参阅公认的答案)。答案还显示了如何加快对任何进程的检查(通过保存进程ID)。
您必须采取的第一步是枚举进程。使用工具帮助或EnumProcesses
执行此操作。如果找到您的进程,请将PID传递给OpenProcess
以获取进程句柄。然后等待进程发出信号。这样就不需要在最初的枚举之外进行轮询。
如果初始枚举找不到进程,则必须重复枚举。使用工具帮助或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.5毫秒。一旦运行并且已知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。Mutex显示为"突变体"。
在Windows上,您可以利用system()
或_wsystem()
快速确定进程是否按名称运行。如果要发送包含.exe
的整个进程名称,只需从函数的第一行中删除字符.exe
即可。
static bool process_exists(std::wstring token)
{
std::wstring cmd_query(std::wstring(L"tasklist|findstr /i "") + token + L".exe">nul 2>&1");
return (_wsystem(cmd_query.data()) == 0) ? (true) : (false);
}
使用Mutex检查进程运行情况。
在检查进程中创建一个具有特定名称的互斥体,并检查该互斥体是否存在于其他进程中。
流程1:
using var mutex = new Mutex(true, LockId, out var created);
LockId
是一个特定的名称。
public const string LockId = "5742D257-CCCC-4F7A-8191-6362609C458D";
进程2可以使用Mutex.TryOpenExisting来检查互斥是否存在。
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 使用基类中的派生方法运行线程,而无需使用模板
- 如何在 C 中使用空的 main() 方法运行函数?
- 如何同时运行 2 种方法
- 使用 c 或 c++ 运行本地服务器的最佳方法
- 类方法 - 数据结构中 For 循环的运行时错误
- 使用本机 JNI 静态方法实现C++ Java 运行时错误
- C ++中的方法覆盖:是编译时还是运行时多态性?
- 还有其他方法可以为乘法表编写循环以获取运行时值吗?
- 如何在长时间运行的方法中等待信号?
- 为什么以相同的数量插入到集合中,基于不同的方法具有不同的运行时间?
- 在另一个 QThread 上运行成员方法时,无法将事件发送到其他线程拥有的对象
- 是否有一种方法可以在运行时停止循环重复一次不止一次
- 是否有一种可接受的运行线程或按顺序执行的方法
- 如何在C++的低优先级线程中运行方法
- 无法在线程运行方法中运行CryptoPP FileSink的情况下终止Qt线程
- 在新进程中运行方法并等待它们完成
- 在opencv(c++)中,在所有像素上运行方法的最快方法是什么
- 使用QThread和QTimer来运行方法
- 运行方法并等待完成所有for循环