我有一个以常规窗口启动并包含“隐藏”按钮的应用程序。单击此按钮后,应用程序将继续运行并在任务管理器中可见,但不再有任何可见窗口。
我尝试了多种方法在 Delphi 中以编程方式查找此应用程序:
使用
GetWindowText
:这不起作用,因为应用程序隐藏时没有窗口。
使用
TProcessEntry32.szExeFile
:这是不可靠的,因为:
TProcessEntry32
列表中使用 WMI 查询:这也无法通过任务管理器中可见的名称找到应用程序。
我的问题是:在给定以下约束的情况下,如何在 Delphi 中创建一个函数来检测该应用程序是否正在运行?
该应用程序旨在不诚实地操纵用户活动跟踪。如前所述,它最初显示为一个窗口,但稍后可以隐藏起来。即使隐藏时,它也会继续模拟用户活动。如前所述,用户可以更改其名称并启动它,因此在这种情况下唯一不变的就是任务管理器中可见的名称。不幸的是,当它隐藏时我无法找到它。下面是我当前使用的代码;如有错误请告诉我。
此代码在应用程序可见时有效(在隐藏时无效)
var WinTitle : array[0..256] of Char;
begin
if GetWindowText(Wnd, WinTitle, SizeOf(WinTitle)) > 0 then
begin
if pos('GDollar', WinTitle) > 0 then
PostMessage(Wnd, WM_CLOSE, 0, 0);
end;
Result := True;
end;
procedure TForm1.btn_1Click(Sender: TObject);
begin
EnumWindows(@EnumWindowsProc, 0);
end;
我尝试过这个 - 但没有运气(而且它 - 显然 - 缓慢得令人痛苦)。
procedure TForm1.btn_2Click(Sender: TObject);
var PHandle, FHandle: THandle;
Process:TProcessEntry32;
Done, Next: Boolean;
WinTitle : array[0..256] of Char;
pn : String;
begin
FHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
Process.dwSize := Sizeof(Process);
Next := Process32First(FHandle, Process);
while Next do
begin
pn := GetProcessNameByPID(GetHWndByPID(process.th32ProcessID));
if pos('GDollar', pn) > 0 then
ShowMessage(pn);
Next := Process32Next(FHandle,Process);
end;
CloseHandle(FHandle);
end;
function TForm1.GetHWndByPID(const hPID: THandle): THandle;
type
PEnumInfo = ^TEnumInfo;
TEnumInfo = record
ProcessID: DWORD;
HWND: THandle;
end;
function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
var PID: DWORD;
begin
GetWindowThreadProcessID(Wnd, @PID);
Result := (PID <> EI.ProcessID) or (not IsWindowVisible(WND)) or (not IsWindowEnabled(WND));
if not Result then EI.HWND := WND;
end;
function FindMainWindow(PID: DWORD): DWORD;
var EI: TEnumInfo;
begin
EI.ProcessID := PID;
EI.HWND := 0;
EnumWindows(@EnumWindowsProc, Integer(@EI));
Result := EI.HWND;
end;
begin
if hPID <> 0
then Result:=FindMainWindow(hPID)
else Result:=0;
end;
function TForm1.GetProcessNameByPID(const PID: DWORD): string;
var
objSWbemLocator, objWMIService: OLEVariant;
colItems: OLEVariant;
colItem: OLEVariant;
oEnum: IEnumvariant;
iValue: LongWord;
begin
Result := ''; // Initialize result to empty string
objSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
objWMIService := objSWbemLocator.ConnectServer('localhost','root\cimv2', '','');
colItems := objWMIService.ExecQuery(Format('SELECT * FROM Win32_Process WHERE ProcessId=%d', [PID]), 'WQL', 0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
if oEnum.Next(1, colItem, iValue) = 0 then
begin
Result := colItem.Name;
colItem := Unassigned;
end;
end;