RAD Studio Efficient Way To Build Your Own Windows Process Viewer In Delphi With Excellent Component Suite

FireWind

Свой
Регистрация
2 Дек 2005
Сообщения
1,957
Реакции
1,199
Credits
4,009
Efficient Way To Build Your Own Windows Process Viewer In Delphi With Excellent Component Suite
February 5, 2021 By Anbarasan

ometimes Developers want to list down or identify the process running in a machine programmatically. How to enumerate among the running processes and services quickly ? Don’t know how to do. Don’t worry. Для просмотра ссылки Войди или Зарегистрируйся System Information Management Suite’s component helps to do that effectively and we will learn how to use the threads TSysProcMonThread and TSvcListMonThread to demonstrate the processes and services respectively.

Platforms: Windows.

Installation Steps:

You can easily install this Component Suite from GetIt Package Manager. The steps are as follows.
  1. Navigate In RAD Studio IDE->Tools->GetIt Package Manager->select Components in Categories->Components->Trail -MiTec system Information Component Suite 14.3 and click Install Button.
  2. Read the license and Click Agree All. An Information dialog saying ‘Requires a restart of RAD studio at the end of the process. Do you want to proceed? click yes and continue.
  3. It will download the plugin and installs it. Once installed Click Restart now.
How to run the Demo app:
  • Navigate to the System Information Management Suite trails setup, Demos folder which is installed during Get It installation e.g) C:UsersDocumentsEmbarcaderoStudio21.0CatalogRepositoryMiTeC-14.3DemosDelphi6
  • Open the PV project in RAD studio 10.4.1 compile and Run the application.
  • This Demo App shows how to list down the running Process and Services in your machine, enumerate among them and access its properties.
Components used in MSIC PV Demo App:
  • TSysProcMonThread: Monitors system and provides running processes, CPU, memory and disk monitoring and provides system information.
  • TSvcListMonThread: Monitors installed services and drivers in real-time and provides their properties.
  • 2 TTabsheet’s one for viewing Process list in TListView and other for viewing Services in TListView .
  • TButton to view the details of the process or service accordingly in a new child form.
Implementation Details:
  • An instance SPM of TSysProcMonThread and SLM of TSvcListMonThread were created. And in regular interval of each thread the Process list and service list is refreshed and updated to the screen using the OnInterval Event handlers
  • On each interval, the Process List( using TProcessRecord ) and Service List (using TServiceRecord) is added to the list view by clearing the existing list.
Код:
procedure Twnd_Main.RefreshProcList(Sender: TSysProcMonThread);
var
  i: Integer;
  r: TProcessRecord;
begin
  PrcList.Items.BeginUpdate;
  try
    PrcList.Items.Clear;
    for i:=0 to Sender.RecordCount-1 do begin
      Sender.GetRecord(i,r);
      with PrcList.Items.Add do begin
        Caption:=r.Name;
        if Is64 and (r.Platform<>64) then
          Caption:=Caption+'*32';
        SubItems.Add(Format('%d',[r.PID]));
        SubItems.Add(FormatTicks(r.UserTime+r.KernelTime,False));
        SubItems.Add(Format('%d KB',[r.VMCounters.WorkingSetSize div 1024]));
        SubItems.Add(Format('%s',[r.CommandLine]));
      end;
    end;
    if PrcList.Tag<>0 then
      PrcList.AlphaSort;
  finally
    PrcList.Items.EndUpdate;
  end;
end;
 
procedure Twnd_Main.RefreshSvcList(Sender: TSvcListMonThread);
var
  i: Integer;
  r: TServiceRecord;
begin
  SvcList.Items.BeginUpdate;
  try
    SvcList.Items.Clear;
    for i:=0 to Sender.RecordCount-1 do begin
      Sender.GetRecord(i,r);
      with SvcList.Items.Add do begin
        Caption:=r.DisplayName;
        if r.Typ=svcUnknown then
          SubItems.Add(Format('%s (%d)',[cSvcType[r.Typ],r._Typ]))
        else
          SubItems.Add(cSvcType[r.Typ]);
        SubItems.Add(cSvcStatus[r.Status]);
        SubItems.Add(cSvcStartup[r.StartUp]);
        SubItems.Add(r.ObjectName);
        SubItems.Add(r.Name);
      end;
    end;
    if SvcList.Tag<>0 then
      SvcList.AlphaSort;
  finally
    SvcList.Items.EndUpdate;
  end;
end;
 

FireWind

Свой
Регистрация
2 Дек 2005
Сообщения
1,957
Реакции
1,199
Credits
4,009
  • Upon Clicking Details for the selected process in the list a new child form is created and data is added to different tab sheets.
Код:
procedure Tdlg_PrcDetails.RefreshData;
var
  i,j,c: Integer;
  r,n: TTreeNode;
  VersionInfo: TVersionInfo;
  m: TModuleRecord;
  h: THandleRecord;
  t: TThreadRecord;
  w: TWindowRecord;
begin
  eName.Text:=FRecord.Name;
  imgIcon.Picture.Icon.Handle:=GetFileIcon(FRecord.ImageName);
  GetFileVerInfo(FRecord.ImageName,VersionInfo);
 
  GenList.Items.Clear;
  with GenList.Items.Add do begin
    Caption:='Description';
    SubItems.Add(VersionInfo.Description);
    ImageIndex:=-3;
  end;
  with GenList.Items.Add do begin
    Caption:='Version';
    SubItems.Add(VersionInfo.FileVersion);
  end;
  with GenList.Items.Add do begin
    Caption:='Product Name';
    SubItems.Add(VersionInfo.ProductName);
  end;
  with GenList.Items.Add do begin
    Caption:='Company Name';
    SubItems.Add(VersionInfo.CompanyName);
  end;
  with GenList.Items.Add do begin
    Caption:='';
    ImageIndex:=-2;
  end;
  with GenList.Items.Add do begin
    Caption:='PID';
    SubItems.Add(Format('%d',[FRecord.PID]));
    ImageIndex:=-3;
  end;
  with GenList.Items.Add do begin
    Caption:='Parent PID';
    SubItems.Add(Format('%d',[FRecord.ParentPID]))
  end;
  with GenList.Items.Add do begin
    Caption:='Image name';
    SubItems.Add(FRecord.ImageName);
  end;
  with GenList.Items.Add do begin
    Caption:='Command line';
    SubItems.Add(FRecord.CommandLine);
  end;
  with GenList.Items.Add do begin
    Caption:='';
    ImageIndex:=-2;
  end;
  if Win32Platform=VER_PLATFORM_WIN32_NT then
    with GenList.Items.Add do begin
      Caption:='User Name';
      SubItems.Add(FRecord.UserName);
      ImageIndex:=-3;
    end;
  with GenList.Items.Add do begin
    Caption:='Priority';
    SubItems.Add(Format('%d',[FRecord.Priority]));
    ImageIndex:=-3;
  end;
  with GenList.Items.Add do begin
    Caption:='Thread Count';
    SubItems.Add(Format('%d',[FRecord.ThreadCount]));
  end;
  with GenList.Items.Add do begin
    Caption:='Handle Count';
    SubItems.Add(Format('%d',[FRecord.HandleCount]));
  end;
 
  c:=FML.Count;
  TabSheet2.Caption:=Format(' Modules (%d) ',[c]);
  ModList.Items.Clear;
  for i:=0 to c-1 do begin
    m:=PModuleRecord(FML[i])^;
    with ModList.Items.Add do begin
      Caption:=m.Name;
      SubItems.Add(Format('%d',[m.ImageSize]));
      SubItems.Add(Format('0x%x',[m.BaseAddress]));
      SubItems.Add(m.VersionInfo.Description);
    end;
  end;
 
  c:=FTL.Count;
  TabSheet5.Caption:=Format(' Threads (%d) ',[c]);
  ThdList.Items.Clear;
  for i:=0 to c-1 do begin
    t:=PThreadRecord(FTL[i])^;
    with ThdList.Items.Add do begin
      Caption:=Format('%d',[t.ID]);
      Subitems.Add(Format('0x%x',[t.StartAddress]));
      Subitems.Add(Format('%d',[t.BasePriority]));
      Subitems.Add(Format('%d',[t.Priority]));
      if TThreadState(t.State)<>StateWait then
        SubItems.Add(cThreadState[TThreadState(t.State)])
      else
        SubItems.Add(Format('%s:%s',[cThreadState[TThreadState(t.State)],cKWaitReason[TKWaitReason(t.WaitReason)]]));
      Subitems.Add(Format('%d',[t.ContextSwitchCount]));
      SubItems.Add(FormatTicks(t.KernelTime));
      SubItems.Add(FormatTicks(t.UserTime));
    end;
  end;
 
  TabSheet3.Caption:=Format(' Child Procs (%d) ',[FCP.Count]);
  CPList.Items.Clear;
  for i:=0 to FCP.Count-1 do
    with CPList.Items.Add do begin
      Caption:=FCP.Names[i];
      SubItems.Add(FCP.ValueFromIndex[i]);
    end;
 
  CntList.Items.Clear;
  with CntList.Items.Add do begin
    Caption:='CPU Times';
    ImageIndex:=-3;
  end;
  with CntList.Items.Add do begin
    Caption:='Kernel Time';
    SubItems.Add(FormatTicks(FRecord.KernelTime));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='User Time';
    SubItems.Add(FormatTicks(FRecord.UserTime));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Total Time';
    SubItems.Add(FormatTicks(FRecord.UserTime+FRecord.KernelTime));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='';
    ImageIndex:=-2;
  end;
  with CntList.Items.Add do begin
    Caption:='I/O Counters';
    ImageIndex:=-3;
  end;
  with CntList.Items.Add do begin
    Caption:='Read Operation Count';
    SubItems.Add(Format('%d',[FRecord.IOCounters.ReadOperationCount.QuadPart]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Write Operation Count';
    SubItems.Add(Format('%d',[FRecord.IOCounters.WriteOperationCount.QuadPart]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Other Operation Count';
    SubItems.Add(Format('%d',[FRecord.IOCounters.OtherOperationCount.QuadPart]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Read Transfer Count';
    SubItems.Add(Format('%d',[FRecord.IOCounters.ReadTransferCount.QuadPart]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Write Transfer Count';
    SubItems.Add(Format('%d',[FRecord.IOCounters.WriteTransferCount.QuadPart]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Other Transfer Count';
    SubItems.Add(Format('%d',[FRecord.IOCounters.OtherTransferCount.QuadPart]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='';
    ImageIndex:=-2;
  end;
  with CntList.Items.Add do begin
    Caption:='Virtual Memory Counters';
    ImageIndex:=-3;
  end;
  with CntList.Items.Add do begin
    Caption:='Page Fault Count';
    SubItems.Add(Format('%d',[FRecord.VMCounters.PageFaultCount]));
    SubItems.Add('-');
  end;
  with CntList.Items.Add do begin
    Caption:='Virtual Size';
    SubItems.Add(Format('%d B',[FRecord.VMCounters.VirtualSize]));
    SubItems.Add(Format('%d B',[FRecord.VMCounters.PeakVirtualSize]));
  end;
  with CntList.Items.Add do begin
    Caption:='Working Set Size';
    SubItems.Add(Format('%d B',[FRecord.VMCounters.WorkingSetSize]));
    SubItems.Add(Format('%d B',[FRecord.VMCounters.PeakWorkingSetSize]));
  end;
  with CntList.Items.Add do begin
    Caption:='Quota Peak Paged Pool Usage';
    SubItems.Add(Format('%d B',[FRecord.VMCounters.QuotaPagedPoolUsage]));
    SubItems.Add(Format('%d B',[FRecord.VMCounters.QuotaPeakPagedPoolUsage]));
  end;
  with CntList.Items.Add do begin
    Caption:='Quota Peak Non Paged Pool Usage';
    SubItems.Add(Format('%d B',[FRecord.VMCounters.QuotaNonPagedPoolUsage]));
    SubItems.Add(Format('%d B',[FRecord.VMCounters.QuotaPeakNonPagedPoolUsage]));
  end;
  with CntList.Items.Add do begin
    Caption:='Pagefile Usage';
    SubItems.Add(Format('%d B',[FRecord.VMCounters.PagefileUsage]));
    SubItems.Add(Format('%d B',[FRecord.VMCounters.PeakPagefileUsage]));
  end;
 
  SecList.Items.Clear;
  with SecList.Items.Add do begin
    Caption:='Groups';
    ImageIndex:=-3;
  end;
  for i:=0 to High(FRecord.Groups) do
    with SecList.Items.Add do begin
      if FRecord.Groups[i].Name='' then
        Caption:=FRecord.Groups[i].SID
      else
        if FRecord.Groups[i].Domain<>'' then
          Caption:=Format('%s%s',[FRecord.Groups[i].Domain,FRecord.Groups[i].Name])
        else
          Caption:=FRecord.Groups[i].Name;
      SubItems.Add(Format('0x%x',[FRecord.Groups[i].Flags]));
    end;
  with SecList.Items.Add do begin
   Caption:='';
   ImageIndex:=-2;
  end;
  with SecList.Items.Add do begin
    Caption:='Privileges';
    ImageIndex:=-3;
  end;
  for i:=0 to High(FRecord.Privileges) do
    with SecList.Items.Add do begin
      Caption:=FRecord.Privileges[i].Name;
      SubItems.Add(IntToStr(Integer(FRecord.Privileges[i].Flags and SE_PRIVILEGE_ENABLED=SE_PRIVILEGE_ENABLED)));
      ImageIndex:=-4;
    end;
 
  c:=FHL.Count;
  TabSheet6.Caption:=Format(' Handles (%d) ',[c]);
  HList.Items.Clear;
  for i:=0 to c-1 do begin
    h:=PHandleRecord(FHL[i])^;
    with HList.Items.Add do begin
      Caption:=Format('0x%x',[h.Handle]);
      SubItems.Add(h.TypeName);
      SubItems.Add(Format('0x%x',[h.Access]));
      SubItems.Add(h.Name);
    end;
  end;
 
  r:=nil;
  c:=FWL.Count;
  TabSheet7.Caption:=Format(' Windows (%d) ',[c]);
  WinTree.Items.Clear;
  for i:=0 to c-1 do begin
    w:=PWindowRecord(FWL[i])^;
    for j:=0 to WinTree.Items.Count-1 do
      if PHandle(WinTree.Items[j].Data)^=w.ParentWin then begin
        r:=WinTree.Items[j];
        Break;
      end;
    n:=WinTree.Items.AddChild(r,Format('(0x%x) "%s": %s',[w.Handle,w.Text,w.ClassName]));
    n.ImageIndex:=Integer(w.Visible);
    n.Data:=Allocmem(SizeOf(THandle));
    n.SelectedIndex:=n.ImageIndex;
    PHandle(n.Data)^:=w.Handle;
  end;
  if WinTree.Items.Count>0 then begin
    WinTree.FullExpand;
    WinTree.Items[0].MakeVisible;
  end;
 
  EnvBox.Items.Text:=FRecord.Environment;
  tsEnv.Caption:=Format('Environment (%d)',[EnvBox.Items.Count]);
 
end;
1612537687256.png
MiTeC PV -Process Details Demo
 

FireWind

Свой
Регистрация
2 Дек 2005
Сообщения
1,957
Реакции
1,199
Credits
4,009
Upon Clicking Details for the selected Service in the list a new child form is created and data is added to different tab sheets.

Код:
procedure Tdlg_SvcDetails.RefreshData;
var
  i: Integer;
  n: TTreeNode;
  r: TServiceRecord;
begin
  eName.Text:=FRecord.DisplayName;
 
  GenList.Items.Clear;
  imgIcon.Picture.Icon.Handle:=GetFileIcon(FRecord.ImageName);
 
  GenList.Items.Clear;
  with GenList.Items.Add do begin
    Caption:='Description';
    SubItems.Add(FRecord.VersionInfo.Description);
    ImageIndex:=-3;
  end;
  with GenList.Items.Add do begin
    Caption:='Version';
    SubItems.Add(FRecord.VersionInfo.FileVersion);
  end;
  with GenList.Items.Add do begin
    Caption:='Product Name';
    SubItems.Add(FRecord.VersionInfo.ProductName);
  end;
  with GenList.Items.Add do begin
    Caption:='Company Name';
    SubItems.Add(FRecord.VersionInfo.CompanyName);
  end;
  with GenList.Items.Add do begin
    Caption:='';
    ImageIndex:=-2;
  end;
 
  with GenList.Items.Add do begin
    Caption:='Service Name';
    SubItems.Add(FRecord.Name);
    ImageIndex:=-3;
  end;
  with GenList.Items.Add do begin
    Caption:='Command line';
    SubItems.Add(FRecord.CmdLine);
  end;
  with GenList.Items.Add do begin
    Caption:='Log On As ';
    SubItems.Add(FRecord.ObjectName);
  end;
  with GenList.Items.Add do begin
    Caption:='Load Order Group';
    SubItems.Add(FRecord.Group);
  end;
  with GenList.Items.Add do begin
    Caption:='Type';
    SubItems.Add(cSvcType[FRecord.Typ]);
  end;
  with GenList.Items.Add do begin
    Caption:='';
    ImageIndex:=-2;
  end;
  with GenList.Items.Add do begin
    Caption:='Status';
    SubItems.Add(cSvcStatus[FRecord.Status]);
    ImageIndex:=-3;
  end;
  with GenList.Items.Add do begin
    Caption:='Startup Mode';
    SubItems.Add(cSvcStartup[FRecord.Startup]);
  end;
  with GenList.Items.Add do begin
    Caption:='Error Control';
    SubItems.Add(cSvcErrorControl[FRecord.ErrCtrl]);
  end;
 
  Dep1Tree.Items.Clear;
  sl.CommaText:=FRecord.DependOnService;
  for i:=0 to sl.Count-1 do begin
    SLM.GetRecordByName(sl[i],r);
    if r.Name<>'' then begin
      n:=Dep1Tree.Items.AddChild(nil,r.DisplayName);
      n.ImageIndex:=0;
      n.HasChildren:=True;
    end;
  end;
  Dep1Tree.AlphaSort;
 
  Dep2Tree.Items.Clear;
  SLM.GetServiceDependants(FRecord.Name,sl);
  for i:=0 to sl.Count-1 do begin
    n:=Dep2Tree.Items.AddChild(nil,sl.ValueFromIndex[i]);
    n.ImageIndex:=0;
    n.HasChildren:=True;
  end;
  Dep2Tree.AlphaSort;
end;
1612537721589.png
MiTeC PV -Services Details Demo
  • Apart from these stopping , starting, pause and resuming the services were implemented in the sample.
It’s that simple to enumerate Process List and Service List running in your machine and view the details of the process. Use this MiTeC component suite and get the job done quickly.

Для просмотра ссылки Войди или Зарегистрируйся