开发者

How can I get other processes' information with Delphi?

I want to make a Task Manager program that displays this information:

  1. Image name
  2. memory usage
  3. P开发者_Go百科ID

How can I do this?


You don't need the J(WS)CL therefore, there is a simple WinAPI call that does almost all you want, and this is CreateToolhelp32Snapshot. To get a snapshot of all running processes, you have to call it as follows:

var
  snapshot: THandle;
begin
  snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 

Now you have a list of all running processes. You can navigate through this list with the Process32First and Process32Next functions, the list entries are PROCESSENTRY32-structures (which contain, amongst others, the process ID and image name).

uses 
  Windows, TLHelp32, SysUtils; 

var 
  snapshot: THandle; 
  ProcEntry: TProcessEntry32; 
  s: String; 
begin
  snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
  if (snapshot <> INVALID_HANDLE_VALUE) then begin 
    ProcEntry.dwSize := SizeOf(ProcessEntry32); 
    if (Process32First(snapshot, ProcEntry)) then begin 
      s := ProcEntry.szExeFile; 
      // s contains image name of the first process 
      while Process32Next(snapshot, ProcEntry) do begin 
        s := ProcEntry.szExeFile; 
        // s contains image name of the current process 
      end; 
    end; 
  end; 
  CloseHandle(snapshot);

However, memory consumption information doesn't seem to be included, but you can get this via another simple API call, GetProcessMemoryInfo

uses
  psAPI;

var
  pmc: TProcessMemoryCounters;
begin
  pmc.cb := SizeOf(pmc) ;
  if GetProcessMemoryInfo(processID, @pmc, SizeOf(pmc)) then
    // Usage in Bytes: pmc.WorkingSetSize
  else
    // fail

You just have to call this function with the process IDs retrieved from the snapshot.


Use the PSAPI (Process Status API). The open source JCL has a Delphi wrapper for the PSAPI.

There are some more good stackoverflow Delphi PSAPI questions you can check for answers.

--jeroen


you can use the WMI Win32_Process class to get all the running process info. addtionally you can check the Win32_PerfFormattedData_PerfProc_Process class to get the performance counters related to CPU and memory usage.

Check this sample

program WMIProcessInfo;

{$APPTYPE CONSOLE}

uses
  SysUtils
  ,ActiveX
  ,ComObj
  ,Variants;


procedure GetWin32_Process;
var
  objWMIService : OLEVariant;
  colItems      : OLEVariant;
  colItem       : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;

  User          : OLEVariant;
  Domain        : OLEVariant;

  function GetWMIObject(const objectName: String): IDispatch;
  var
    chEaten: Integer;
    BindCtx: IBindCtx;
      Moniker: IMoniker;
  begin
    OleCheck(CreateBindCtx(0, bindCtx));
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
  end;

begin
  objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
  colItems      := objWMIService.ExecQuery('SELECT * FROM Win32_Process','WQL',0);
  oEnum         := IUnknown(colItems._NewEnum) as IEnumVariant;

      WriteLn(Format('%-20s %6s %10s %10s %10s',['Caption','PID','User','Domain','Working Set ( Kb Memory)']));
  while oEnum.Next(1, colItem, iValue) = 0 do
  begin
      colItem.GetOwner(User,Domain);
      if colItem.GetOwner( User, Domain ) =0 then //get the user and domain
      WriteLn(Format('%-20s %6s %10s %10s %10s',[colItem.Caption,colItem.ProcessId,User,Domain,colItem.WorkingSetSize / 1024]))
      else
      WriteLn(Format('%-20s %6s %10s %10s %10s',[colItem.Caption,colItem.ProcessId,'','',colItem.WorkingSetSize / 1024]));

  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_Process;
      Readln;
    finally
    CoUninitialize;
    end;
 except
    on E:Exception do
    Begin
        Writeln(E.Classname, ': ', E.Message);
        Readln;
    End;
  end;
end.


In Jwscl there is a class that can do this for you (JwsclTerminalServer):

 var
   ATerminalServer: TJwTerminalServer;
   i: Integer;
 begin
   // Create Terminal Server instance and allocate memory for it
   ATerminalServer := TjwTerminalServer.Create;

   // Set servername (only in case of remote server)
   ATerminalServer.Server := 'TS001';

   // Remember that EnumerateProcesses will automatically connect to the
   // Terminal Server for you. The connect function raises an Exception
   // if the connection attempt was unsuccessfull, so better use try..except
   try
     if ATerminalServer.EnumerateProcesses then
     begin

       // Now loop through the list
       for i := 0 to ATerminalServer.Processes.Count - 1 do
       begin
         Memo1.Lines.Add(ATerminalServer.Processes[i].ProcessName);
       end;

     end;
   except
     on E: EJwsclWinCallFailedException do
     begin
       // Handle Exception here
     end;
   end;

   // Free Memory
   ATerminalServer.Free;
 end;

Although the unit is aimed at Terminal Server this part works both with and without and as a bonus you can use it on remote systems as well.

For each process detailed information is returned, check the docs for details.

For memory usage you can use the ProcessMemUsage and ProcessVirtualSize properties, for the Pid there is the ProcessId property


ProcessInfo provides basic information about running processes in Windows. It is open-source, and contains a demo of a task manager.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜