2009-07-09 46 views
6

¿Cómo obtengo una lista de los procesos en ejecución (con detalles de PID, Propietario, etc.) en mi máquina utilizando Delphi?Enumerar procesos en ejecución en Delphi

EDIT: Ninguna de las soluciones propuestas me da el usuario propietario del proceso, tales como única información PID, ExeName etc ...

+1

Debería usar el JCL propuesto a continuación. Usar directamente las funciones de toolhelp o EnumProcesses es bastante complicado. –

Respuesta

10

Una forma es usar Tool Help library (ver unidad TlHelp32), o EnumProcesses en Windows NT (ver unidad PsAPI). Eche un vistazo a JclSysInfo.RunningProcessesList en el JCL para un ejemplo.

Aquí está un ejemplo rápido de cómo obtener el nombre de usuario de un proceso:

type 
    PTokenUser = ^TTokenUser; 
    TTokenUser = packed record 
    User: SID_AND_ATTRIBUTES; 
    end; 

function GetProcessUserName(ProcessID: Cardinal; out DomainName, UserName: string): Boolean; 
var 
    ProcessHandle, ProcessToken: THandle; 
    InfoSize, UserNameSize, DomainNameSize: Cardinal; 
    User: PTokenUser; 
    Use: SID_NAME_USE; 
    _DomainName, _UserName: array[0..255] of Char; 
begin 
    Result := False; 
    DomainName := ''; 
    UserName := ''; 

    ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessID); 
    if ProcessHandle = 0 then 
    Exit; 

    try 
    if not OpenProcessToken(ProcessHandle, TOKEN_QUERY, ProcessToken) then 
     Exit; 

    try 
     GetTokenInformation(ProcessToken, TokenUser, nil, 0, InfoSize); 
     User := AllocMem(InfoSize * 2); 
     try 
     if GetTokenInformation(ProcessToken, TokenUser, User, InfoSize * 2, InfoSize) then 
     begin 
      DomainNameSize := SizeOf(_DomainName); 
      UserNameSize := SizeOf(_UserName); 

      Result := LookupAccountSid(nil, User^.User.Sid, _UserName, UserNameSize, _DomainName, DomainNameSize, Use); 

      if Result then 
      begin 
      SetString(DomainName, _DomainName, StrLen(_DomainName)); 
      SetString(UserName, _UserName, StrLen(_UserName)); 
      end; 
     end; 
     finally 
     FreeMem(User); 
     end; 
    finally 
     CloseHandle(ProcessToken); 
    end; 
    finally 
    CloseHandle(ProcessHandle); 
    end; 
end; 
+0

Desafortunadamente, esto no soluciona mi necesidad de encontrar el propietario de un proceso – Marius

+0

Utilizando la biblioteca Tool Help, está el campo th32ParentProcessID en las entradas devueltas. JclSysInfo en sí mismo no lo usa, pero puede usarlo como punto de partida. –

+0

TOndrej - En realidad estaba pensando en el usuario que posee/ejecuta el proceso – Marius

3

Ésta es la función que usamos para comprobar si existe un proceso, el FProcessEntry32 contiene toda la información sobre el proceso, por lo deberías poder extenderlo a todo lo que necesites.

fue tomado de here

uses TlHelp32 

function processExists(exeFileName: string): Boolean; 
{description checks if the process is running 
URL: http://www.swissdelphicenter.ch/torry/showcode.php?id=2554} 
var 
    ContinueLoop: BOOL; 
    FSnapshotHandle: THandle; 
    FProcessEntry32: TProcessEntry32; 
begin 
    FSnapshotHandle  := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
    FProcessEntry32.dwSize := SizeOf(FProcessEntry32); 
    ContinueLoop   := Process32First(FSnapshotHandle, FProcessEntry32); 
    Result := False; 


    while Integer(ContinueLoop) <> 0 do 
    begin 

    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = 
     UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = 
     UpperCase(ExeFileName))) then 
    begin 
     Result := True; 
    end; 

    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32); 
    end; 
    CloseHandle(FSnapshotHandle); 
end; 

El registro TProcessEntry32 se ve así:

tagPROCESSENTRY32 = packed record 
    dwSize: DWORD; 
    cntUsage: DWORD; 
    th32ProcessID: DWORD;  // this process 
    th32DefaultHeapID: DWORD; 
    th32ModuleID: DWORD;  // associated exe 
    cntThreads: DWORD; 
    th32ParentProcessID: DWORD; // this process's parent process 
    pcPriClassBase: Longint; // Base priority of process's threads 
    dwFlags: DWORD; 
    szExeFile: array[0..MAX_PATH - 1] of Char;// Path 
    end; 
+0

Gracias por el código, funciona genial. Por cierto, puedes reemplazar esa cláusula if con 'if StrUtils.EndsText (exeFileName, FProcessEntry32.szExeFile) then'. – saastn

2

This class will give you a list of all open windows (enumerados a continuación) con PID, título, dimensiones, etc. No está funcionando exactamente la información procesos , pero lo he usado para encontrar aplicaciones a través de él.

// Window List Component 1.5 by Jerry Ryle 
// 
// Aaugh! I accidentally uploaded the wrong source 
// which had a nasty bug in the refresh procedure! 
// Thanks to Serge, who found my mistake and suggested 
// a few other improvements! 
// 
// This component will enumerate windows and return 
// information about them in the Windows property. 
// The component currently returns a handle, caption text, 
// associated ProcessID, visibility, and dimensions. 
// For documentation, please read the accompanying 
// WindowList.txt 
// 
// This component is completely free of course. If you find 
// it useful, and are compelled to send me cash, beer, or 
// dead things in envelopes, please feel free to do so. 
// 
// email me if you make it better: [email protected] 

unit WindowList; 

interface 

uses 
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; 

type 

    TWindowObject = record 
        WinHandle : HWnd; // Window Handle 
        WinCaption : String; // Window Caption Text (If any) 
        ProcessID : Integer; // Process the window belongs to 
        IsVisible : Boolean; // Is the window visible? 
        IsEnabled : Boolean; // Is the window enabled for mouse/keyboard input? 
        IsIconic : Boolean; // Is the window minimized? 
        WindowRect : TRect; // Window Dimensions 
        // Add more properties here if you like, 
        // then fill them in at the WindowCallback 
        // function. 
        end; 
    PTWindowObject = ^TWindowObject; 

    TWindowList = class(TComponent) 
    private 
    WindowLst : TList; 
    FCount : Integer; 
    protected 
    Function GetAWindow(Index : Integer) : TWindowObject; 
    public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 

    Procedure Refresh; 
    Property Windows[Index : Integer]: TWindowObject read GetAWindow; 
    Property Count : Integer read FCount; 
    published 
    // Published declarations 
    end; 

procedure Register; 

implementation 

// Note that this function is not a member of WindowList. 
// Therefore, the list to be filled needs to be passed 
// as a pointer. Note that this is passed as a VAR. if you 
// don't do this, bad things happen in memory. 

Function WindowCallback(WHandle : HWnd; Var Parm : Pointer) : Boolean; stdcall; 
// This function is called once for each window 
Var MyString : PChar; 
    MyInt : Integer; 
    MyWindowPtr : ^TWindowObject; 
begin 
    New(MyWindowPtr); 

    // Window Handle (Passed by the enumeration) 
    MyWindowPtr.WinHandle := WHandle; 

    // Window text 
    MyString := Allocmem(255); 
    GetWindowText(WHandle,MyString,255); 
    MyWindowPtr.WinCaption := String(MyString); 
    FreeMem(MyString,255); 

    // Process ID 
    MyInt := 0; 
    MyWindowPtr.ProcessID := GetWindowThreadProcessId(WHandle,@MyInt); 

    // Visiblity 
    MyWindowPtr.IsVisible := IsWindowVisible(WHandle); 

    // Enabled 
    MyWindowPtr.IsEnabled := IsWindowEnabled(WHandle); 

    // Iconic 
    MyWindowPtr.IsIconic := IsIconic(WHandle); 

    // Window Dimensions 
    MyWindowPtr.WindowRect := Rect(0,0,0,0); 
    GetWindowRect(WHandle,MyWindowPtr.WindowRect); 

    // Add the structure to the list. Do not dereference Parm... 
    // once again, bad things happen. 
    TList(Parm).Add(MyWindowPtr); 
    Result := True; // Everything's okay. Continue to enumerate windows 
end; 

constructor TWindowList.Create(AOwner: TComponent); 
var MyWindowPtr : PTWindowObject; 
begin 
    inherited; 
    WindowLst := TList.Create; 

    // Thanks Serge, I should've done this from the start :) 
    // Sloppy me. 
    If Not (csDesigning in ComponentState) Then 
    Begin 
     EnumWindows(@WindowCallback,Longint(@WindowLst)); 
     FCount := WindowLst.Count; 
    End 
    Else 
    FCount := 0; 
end; 

destructor TWindowList.Destroy; 
var I : Integer; 
begin 
    If WindowLst.Count > 0 Then 
    Begin 
     For I := 0 To (WindowLst.Count - 1) Do 
     Dispose(PTWindowObject(WindowLst[I])); 
    End; 
    WindowLst.Free; 
    inherited; 
end; 

procedure TWindowList.Refresh; 
begin 
    WindowLst.Clear; {Clear the list!} 
    EnumWindows(@WindowCallback,Longint(@WindowLst)); 
    FCount := WindowLst.Count; 
end; 

function TWindowList.GetAWindow(Index : Integer) : TWindowObject; 
begin 
    Result := PTWindowObject(WindowLst[Index])^; 
end; 

procedure Register; 
begin 
    RegisterComponents('System', [TWindowList]); 
end; 

end. 
Cuestiones relacionadas