Search code examples
inno-setuppascalscript

How to get the current process list in windows


I'm trying to show all processes which are currently running on my system. Can any one guide me to do that.


Solution

  • I would use WMI for this task since WMI can list also 64-bit processes which I think the Windows API way cannot. Here is an example which uses the Win32_Process class to query list of running processes:

    [Setup]
    AppName=My Program
    AppVersion=1.5
    DefaultDirName={pf}\My Program
    
    [Code]
    const
      WM_SETREDRAW = $000B;
    var
      ProcessList: TNewListBox;
    
    // this is a substitution for missing BeginUpdate method
    // of TStrings class
    procedure WinControlBeginUpdate(Control: TWinControl);
    begin
      SendMessage(Control.Handle, WM_SETREDRAW, 0, 0);
    end;
    
    // this is a substitution for missing EndUpdate method
    // of TStrings class
    procedure WinControlEndUpdate(Control: TWinControl);
    begin
      SendMessage(Control.Handle, WM_SETREDRAW, 1, 0);
      Control.Refresh;
    end;
    
    function GetProcessNames(Items: TStrings): Integer;
    var
      I: Integer;
      WQLQuery: string;
      WbemLocator: Variant;
      WbemServices: Variant;
      WbemObject: Variant;
      WbemObjectSet: Variant;
    begin
      Result := 0;
    
      WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
      WbemServices := WbemLocator.ConnectServer('localhost', 'root\CIMV2');
    
      WQLQuery := 'SELECT Name FROM Win32_Process';
    
      WbemObjectSet := WbemServices.ExecQuery(WQLQuery);
      if not VarIsNull(WbemObjectSet) and (WbemObjectSet.Count > 0) then
      begin
        Items.Clear;
        for I := 0 to WbemObjectSet.Count - 1 do
        begin
          WbemObject := WbemObjectSet.ItemIndex(I);
          if not VarIsNull(WbemObject) then
            Items.Add(WbemObject.Name);
        end;
        Result := Items.Count;
      end;
    end;
    
    procedure RefreshButtonClick(Sender: TObject);
    begin
      // this try..finally block is used to reduce annoying visual effects
      // when filling the list box; Inno Setup doesn't publish BeginUpdate,
      // EndUpdate method pair, hence this home brewn solution
      WinControlBeginUpdate(ProcessList);
      try
        GetProcessNames(ProcessList.Items);
      finally
        WinControlEndUpdate(ProcessList);
      end;
    end;
    
    procedure InitializeWizard;
    var
      RefreshBtn: TNewButton;
      ProcessPage: TWizardPage;
    begin
      ProcessPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');
    
      ProcessList := TNewListBox.Create(WizardForm);
      ProcessList.Parent := ProcessPage.Surface;
      ProcessList.SetBounds(0, 0, ProcessPage.SurfaceWidth,
        ProcessPage.SurfaceHeight - 33);
    
      RefreshBtn := TNewButton.Create(WizardForm);
      RefreshBtn.Parent := ProcessPage.Surface;
      RefreshBtn.Left := 0;
      RefreshBtn.Top := ProcessPage.SurfaceHeight - RefreshBtn.Height;
      RefreshBtn.Caption := 'Refresh';
      RefreshBtn.OnClick := @RefreshButtonClick;
    end;