简体   繁体   English

枚举Delphi中的运行进程

[英]Enumerate running processes in Delphi

How do I get a list of the running processes (with details of PID, Owner etc) on my machine using Delphi? 如何使用Delphi在我的机器上获取正在运行的进程列表(包含PID,所有者等的详细信息)?

EDIT: None of the solutions proposed gives me the user that owns the process, only info such as PID, ExeName etc... 编辑:所提出的解决方案都没有给我拥有该进程的用户,只有PID,ExeName等信息......

One way is using the Tool Help library (see TlHelp32 unit), or EnumProcesses on Windows NT (see PsAPI unit). 一种方法是使用工具帮助库 (见TlHelp32单元),或EnumProcesses在Windows NT(见PSAPI单位)。 Have a look at JclSysInfo.RunningProcessesList in the JCL for an example. 有关示例,请查看JCL中的JclSysInfo.RunningProcessesList

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;

You have to use: 你必须使用:

PROCESSENTRY32 Structure will contain all the informations that you may need. PROCESSENTRY32结构将包含您可能需要的所有信息。

The documentation is from MDSN, for C++, but it's the same in Delphi. 该文档是从MDSN,对于C ++,但它是在Delphi中一样

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. 这是我们用来检查进程是否存在的函数,FProcessEntry32保存了进程的所有信息,因此您应该能够将它扩展到您需要的所有内容。

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: TProcessEntry32记录如下所示:

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;

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. 这个类将为您提供所有打开的窗口 (下面列出) 的列表,其中包含PID,标题,尺寸等。它并不完全正在运行流程信息,但我已经用它来通过它查找应用程序。

//   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:  gryle@calpoly.edu

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.

You could look at using the WMISet components ($69 single licence, $199 for site licence, trial version available). 您可以查看使用WMISet组件 (69美元的单一许可证,199美元的站点许可证,可用的试用版本)。 The TWmiProcessControl component seems to encapsulate calls to Win32_Process. TWmiProcessControl组件似乎封装了对Win32_Process的调用。 They also have an example of getting a process owner . 他们还有一个获得流程所有者的例子。

我认为Madshi madKernel非常有趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM