Uchwyt na podstawie nazwy pliku exe programu

olesio

Czasami widziałem na forum pytania, jak pobrać PID albo HWND aplikacji na podstawie nazwy plku wykonywalnego.
Poniżej prezentuje moduł, który to robi. Wystarczy poniższy kod zapisać do pliku get_hwnd_from_exename. pas i
dodać go do sekcji uses i wywołać funkcję ExeProcessToHWnd jako parametr podając .exe programu, na przykład:

var
  Opera_H : HWND;
begin
  Opera_H := ExeProcessToHWnd('opera.exe');
  ShowMessage(IntToStr(Opera_H));
// ...
end;

Poniższy kod napisałem na podstawie kodów znalezionych w google. Bardzo ważne jest aby zmienne PidNum oraz
AHandle były globalnymi czyli poza kodem samej funkcji zwracającej HWND. Inaczej funkcja zwróci błędne wartości.

Oto pełen kod modułu, który można również pobrać w postaci skompresowanej: get_hwnd_from_exename.zip

unit get_hwnd_from_exename;

interface

uses
  Windows, SysUtils, TlHelp32;

function ExeProcessToHWnd(ProcessName : string) : HWND;

implementation

var
  PidNum : DWORD;
  AHandle : HWND;

function ExeProcessToHWnd(ProcessName : string) : HWND;
  function EnumProcess(hHwnd : HWND; lParam : integer) : boolean; stdcall;
  var
    pPid : DWORD;
  begin
    Result := (hHwnd <> 0);
    if Result = True then
    begin
      GetWindowThreadProcessId(hHwnd, pPid);
      if pPid = PidNum then
      begin
        if (GetWindowLong(hHWND, GWL_HWNDPARENT) = 0)
          and (IsWindowVisible(hHWND) or IsIconic(hHWND)) then
        begin
          AHandle := hHWND;
        end;
      end;
    end;
    Result := True;
  end;

  function ProcessIDFromAppname32(AppName : string) : DWORD;
  var
    SnapShot : THandle;
    processEntry : TProcessEntry32;
  begin
    Result := 0;
    AppName := AnsiUpperCase(AppName);
    SnapShot := CreateToolhelp32SnapShot(TH32CS_SNAPPROCESS, 0);
    if SnapShot <> 0 then
    try
      ProcessEntry.dwSize := SizeOf(ProcessEntry);
      if Process32First(SnapShot, ProcessEntry) then
        repeat
          if Pos(AppName, AnsiUpperCase(ExtractFilename
            (StrPas(processEntry.szExeFile)))) > 0 then
          begin
            Result := ProcessEntry.th32ProcessID;
            Break;
          end;
        until not Process32Next(SnapShot, ProcessEntry);
    finally
      CloseHandle(SnapShot);
    end;
  end;

begin
  PidNum := ProcessIDFromAppname32(ProcessName);
  EnumWindows(@EnumProcess, 0);
  Result := AHandle;
end;

end.

0 komentarzy