tags:

views:

1478

answers:

6

How do I get a list of the running processes (with details of PID, Owner etc) on my machine using Delphi?

EDIT: None of the solutions proposed gives me the user that owns the process, only info such as PID, ExeName etc...

+2  A: 

You have to use:

PROCESSENTRY32 Structure will contain all the informations that you may need.

The documentation is from MDSN, for C++, but it's the same in Delphi.

Nick D
+7  A: 

One way is using the Tool Help library (see TlHelp32 unit), or EnumProcesses on Windows NT (see PsAPI unit). Have a look at JclSysInfo.RunningProcessesList in the JCL for an example.

Here's a quick example of how to get the user name of a process:

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;
TOndrej
Unfortunately, this does not address my need for finding the owner of a process
Marius
Using the Tool Help library, there's the th32ParentProcessID field in returned entries. JclSysInfo itself does not use it but you can use it as a starting point.
TOndrej
TOndrej - I was actually thinking of the user that owns/runs the process
Marius
I see. I assumed that by "owner" you meant the parent process.I've added code to get the user name of the account under which the process is running.
TOndrej
+1  A: 

This is the function we use to check if a process exists, the FProcessEntry32 holds all the info on the process, so you should be able to extend it to what every you need.

it was taken from 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;

The TProcessEntry32 record looks like so:

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;
Re0sless
+2  A: 

This class will give you a list of all open windows (listed below) with PID, caption, dimensions, etc. It's not exactly running processes information, but I've used it to find apps via it.

//   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.
Pauk
+1  A: 

You could look at using the WMISet components ($69 single licence, $199 for site licence, trial version available). The TWmiProcessControl component seems to encapsulate calls to Win32_Process. They also have an example of getting a process owner.

Pauk
+1  A: 

I think Madshi madKernel could be interesting to check out.

Vegar
Yes, highly recommended.
TOndrej