要检查进程是否正在运行,可以使用" CreateToolHelp32SnapShot" Windows API函数并枚举正在运行的进程。答案问题中给出了示例C / C ++代码: Check whether one specific process is running on windows with C++
我的问题是,如果您知道自己正在寻找特定的流程,是否有更快的方式找到答案,而无需依次检查每个流程?我们需要定期检查我们的远程支持工具TeamViewer.exe是否正在运行。请注意,TeamViewer是由第三方编写的,我们无法控制它或了解EXE的内部。
编辑:
TeamViewer提供了一些有关其进程内部的信息,可用于在此实例中加快速度(请参阅已接受的答案)。答案还说明了如何加快对任何进程的检查(通过保存进程ID)。
答案 0 :(得分:2)
您必须采取的第一步涉及枚举流程。使用toolhelp或EnumProcesses
执行此操作。如果找到您的进程,请将PID传递给OpenProcess
以获取进程句柄。然后等待该过程发出信号。这样就可以避免在最初的枚举之外进行轮询。
如果您的初始枚举无法找到该过程,则必须重复枚举。使用任何一个工具帮助或EnumProcesses
结果更有效。也许扼杀了民意调查。您也可以选择使用WMI通知新进程创建,这样就完全避免了轮询的需要。
答案 1 :(得分:1)
在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);
}
答案 2 :(得分:0)
经过大量研究(以及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。互斥体显示为“突变体”。
答案 3 :(得分:0)
使用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检查互斥体是否存在。