Jump to content
JohnLM

How do I show a complete list of running processes?

Recommended Posts

I have this routine that lists all running processes in a listbox under Windows 7.

 

However, it is not a complete list as I thought, because when I load up the Task Manager, it has more entries (when I select '[y] show processes from all users'). 

 

Here is a complete project listing showing two working methods to obtain the running processes into a listbox.  The only limitations with these are that they

show less entries than what the Task Manager shows.  

 

Question:  How do I obtain that same listing in delphi that the Task Manager shows?  TIA. 

 

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ComCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    m1: TMemo;
    lb1: TListBox;
    btnGetProcesses1: TButton;
    Splitter1: TSplitter;
    btnPause: TButton;
    st1: TStaticText;
    btnGetProcesses2: TButton;
    procedure btnPauseClick(Sender: TObject);
    procedure btnGetProcesses2Click(Sender: TObject);
    procedure btnGetProcesses1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure GetProcesses_1;
    procedure GetProcesses_2;
  end;

var
  Form1: TForm1;
  ts: tstrings;
  n: integer=0; // out counter for the listbox of items.

implementation

{$R *.dfm}

uses tlHelp32;

procedure tform1.GetProcesses_1; // #1
var
  handler: THandle;
  data: TProcessEntry32;
  PID: cardinal;

  function GetName: string;
  var i:byte;
  begin
     Result := '';
     i := 0;
     while data.szExeFile[i] <> '' do
     begin
        Result := Result + data.szExeFile[i];  //PID := data.th32ProcessID;
        Inc(i);
     end;
   end;

begin
  n:=0;
  ts:=tstringlist.Create;
  Data.dwSize := SizeOf(Data);
  form1.DoubleBuffered:=true;
  lb1.DoubleBuffered := true;
  lb1.Items.BeginUpdate;
  lb1.Items.Clear;
  lb1.Sorted:=true;
  handler := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
  if Process32First(handler, data) then
  begin
    ts.Add(GetName());
    //lb1.Items.Add({inttostr(data.th32ProcessID) + ': '+}GetName());
    while Process32Next(handler, data) do begin
       ts.Add(GetName());
       inc(n);
       //lb1.Items.Add({inttostr(data.th32ProcessID) + ': '+}GetName());
    end;
   end
   else
      ShowMessage('Error');
   lb1.Items.EndUpdate;
   lb1.Items.Assign(ts);
   st1.Caption := inttostr(n);
   ts.Free;
end;

procedure TForm1.btnGetProcesses1Click(Sender: TObject);
begin
 GetProcesses_1;
end;

procedure tform1.getprocesses_2; // method #2, from https://www.vbforums.com/showthread.php?350779-Delphi-Getting-Running-processes-into-a-List-Box-and-Kill-Selected
var
  MyHandle: THandle;
  Struct: TProcessEntry32;
begin  n:=0;
  try
    MyHandle:=CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
    Struct.dwSize:=Sizeof(TProcessEntry32);
    if Process32First(MyHandle, Struct) then form1.lb1.Items.Add(Struct.szExeFile);
    while Process32Next(MyHandle, Struct) do begin
      form1.lb1.Items.Add(Struct.szExeFile);
      inc(n);
    end;
    except on exception do
      ShowMessage('Error showing process list');
  end
end;

procedure TForm1.btnGetProcesses2Click(Sender: TObject);  // method #2
begin
  n:=0;
  getprocesses_2;
  st1.Caption := inttostr(n);
end;

end.

 

Share this post


Link to post
17 hours ago, JohnLM said:

I have this routine that lists all running processes in a listbox under Windows 7.

As Anders mentioned, you likely don't have permissions to retrieve all processes for other users.  That being said, you might consider trying EnumProcesses() and see if it returns more entries.

 

That being said, there are quite a number of issues with the code you have shown:

  • You are leaking the THandle returned by CreateToolhelp32Snapshot().
  • GetName() is over-complicated.  The data.szExeFile value is guaranteed to be null-terminated, so your loop is completely unnecessary (not to mention your use of a Byte for the loop counter means you might potentially truncate long filenames). You can simply assign the data.szExeFile value as-is to the Result without concatenating Char-by-Char (also, your comparison of a single Char to a blank string makes no sense at all).  For that matter, you could just get rid of GetName() altogether and simply add data.szExeName as-is to your TStrings.

  • You are not protecting your code from unexpected exceptions, which will cause several leaks if something goes wrong.  There are several places in your code where you should be using try..finally blocks to free/release resources properly.

  • You don't need to use the global Form1 variable inside of TForm1's own methods.  Use each method's Self pointer instead.

 

 

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×