Как получить приложения из диспетчера задач Windows (вкладка «Приложения») + их расположение на жестком диске из Delphi - PullRequest
5 голосов
/ 01 августа 2010

Я хотел бы получить список программ, работающих и видимых во вкладке «Программы» диспетчера задач Windows (не вкладка «Процессы»), и получить их расположение на жестком диске?
Мне нужно сделать это в Delphi.Кто-нибудь может помочь?

Ответы [ 2 ]

4 голосов
/ 01 августа 2010

Насколько я знаю, вкладка «Приложение» в диспетчере задач представляет собой список окон верхнего уровня, которые не принадлежат другим окнам, не имеют родительских окон и не являются окнами инструментов.В моем Process Info у меня есть модуль AppInfo.pas, который возвращает список окон с такими характеристиками, и этот список совпадает с тем, что вы видите в диспетчере задач.Вот основная часть кода, которая написана как функция обратного вызова для функции API EnumWindows:

{$IFDEF DELPHI2007UP}
class function TAppWindowCollection.EnumWinProc(wHandle: HWND; lparam: integer): Bool;
{$ELSE}
function EnumWinProc(wHandle: HWND; lparam: integer): Bool; stdcall;
{$ENDIF}
Const
  MAX_TEXT = MAX_PATH;
var
  WindowItem : TWindowItem;
  strText,strClass : array [0..MAX_TEXT] of char;
  IsAppMainWin : Boolean;
begin
  //Check if the window is a visible application main window.
  IsAppMainWin := IsWindowVisible(wHandle)          AND                        //Visible
                  (GetWindow(wHandle,GW_OWNER) = 0) AND                        //Not owned by other windows
                  (GetParent(wHandle) = 0)          AND                        //Does not have any parent
                  (GetWindowLong(wHandle,GWL_EXSTYLE) AND WS_EX_TOOLWINDOW = 0); //Not a tool window

  if IsAppMainWin then
  begin
    WindowItem := TAppWindowCollection(lparam).Add;

    GetWindowText(wHandle,strText,MAX_TEXT);
    GetClassName(wHandle,strClass,MAX_TEXT);

    WindowItem.FCaption := strText;
    WindowItem.FHandle := wHandle;
    WindowItem.FWindowClass := strClass;
    GetWindowThreadProcessId(wHandle,WindowItem.FProcessID);
  end;

  Result := True;
end;

Полный исходный код вы можете найти в AppInfo.pas .

и получить их местоположение на жестком диске

Это всего лишь окна.Если вы хотите получить путь к файлу EXE, соответствующему каждому элементу, вы должны сначала найти процесс, которому принадлежит это окно, используя функцию API GetWindowThreadProcessID .Это то, что я сделал в приведенном выше коде.Получив идентификатор процесса, вы можете получить из него дескриптор процесса и перечислить его модули.Первый модуль - это основной EXE-файл.Я реализовал это в моем компоненте TProcessInfo, который входит в тот же пакет с AppInfo.pas.

2 голосов
/ 07 января 2013

Вот полное автономное решение (больше нет неработающих ссылок)

program ApplicationList;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  Winapi.Windows,
  Winapi.PsAPI;

function GetPathFromPID( const PID : cardinal ) : string;
var
  hProcess : THandle;
  path :     array [0 .. MAX_PATH - 1] of char;
begin
  hProcess := OpenProcess( PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID );
  if hProcess <> 0
  then
    try
      if GetModuleFileNameEx( hProcess, 0, path, MAX_PATH ) = 0
      then
        RaiseLastOSError;
      Result := path;
    finally
      CloseHandle( hProcess )
    end
  else
    RaiseLastOSError;
end;

function EnumWinProc( wHandle : hWnd; lparam : integer ) : Bool; stdcall;
Const
  MAX_TEXT = MAX_PATH;
var
  strText, strClass : array [0 .. MAX_TEXT] of char;
  strPath :           string;
  IsAppMainWin :      Boolean;
  ProcId :            cardinal;
begin
  // Check if the window is a visible application main window.
  IsAppMainWin := IsWindowVisible( wHandle ) AND // Visible
    ( GetWindow( wHandle, GW_OWNER ) = 0 ) AND   // Not owned by other windows
    ( GetParent( wHandle ) = 0 ) AND             // Does not have any parent
    ( GetWindowLong( wHandle, GWL_EXSTYLE ) AND WS_EX_TOOLWINDOW = 0 ); // Not a tool window

  if IsAppMainWin
  then
    begin

      GetWindowText( wHandle, strText, MAX_TEXT );
      GetClassName( wHandle, strClass, MAX_TEXT );

      GetWindowThreadProcessID( wHandle, ProcId );

      try
        strPath := GetPathFromPID( ProcId );
      except
        strPath := '???';
      end;

      WriteLn( ProcId, ' - ', strClass, ' - ', strText, ' - ', strPath );
    end;

  Result := True;
end;

procedure DoEnumWindows;
var
  FirstWnd : cardinal;
begin
  EnumWindows( @EnumWinProc, cardinal( @FirstWnd ) );
end;

begin
  try
    DoEnumWindows;
  except
    on E : Exception do
      WriteLn( E.ClassName, ': ', E.Message );
  end;

  ReadLn;

end.
...