如何检查进程是否属于当前用户?

时间:2016-11-18 10:03:06

标签: delphi process

我正在尝试获取属于当前用户的进程的PID,但我不知道如何检查进程所有者。

这是我的代码(缺少用户的检查条件):

uses
  TlHelp32, ...;

type
  TCardinalArray = array of Cardinal;

function GetCurrentUserPIDs(const AProcessName : string) : TCardinalArray;
var
  ContinueLoop: boolean;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  SetLength(Result, 0);
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  while(ContinueLoop) do
  begin
    if(SameText(FProcessEntry32.szExeFile, AProcessName)) then
    begin
      if((* is this my process? *)) then
      begin
        SetLength(Result, Length(Result) + 1);
        Result[Length(Result) - 1] := FProcessEntry32.th32ProcessID;
      end;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;

1 个答案:

答案 0 :(得分:2)

我找到了GetUserAndDomainFromPID功能,可以轻松完成任务。

正如Sertac Akyuz建议的那样,该函数使用OpenProcessTokenGetTokenInformation。它还使用LookupAccountSid

uses
  TlHelp32;

type
  PTOKEN_USER = ^TOKEN_USER;
  _TOKEN_USER = record
    User: TSidAndAttributes;
  end;
  TOKEN_USER = _TOKEN_USER;

function GetUserAndDomainFromPID(ProcessId: DWORD;
  var User, Domain: string): Boolean;
var
  hToken: THandle;
  cbBuf: Cardinal;
  ptiUser: PTOKEN_USER;
  snu: SID_NAME_USE;
  ProcessHandle: THandle;
  UserSize, DomainSize: DWORD;
  bSuccess: Boolean;
begin
  Result := False;
  ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessId);
  if ProcessHandle <> 0 then
  begin
  //  EnableProcessPrivilege(ProcessHandle, 'SeSecurityPrivilege', True);
    if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then
    begin
      bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf);
      ptiUser  := nil;
      while (not bSuccess) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do
      begin
        ReallocMem(ptiUser, cbBuf);
        bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf);
      end;
      CloseHandle(hToken);

      if not bSuccess then
      begin
        Exit;
      end;

      UserSize := 0;
      DomainSize := 0;
      LookupAccountSid(nil, ptiUser.User.Sid, nil, UserSize, nil, DomainSize, snu);
      if (UserSize <> 0) and (DomainSize <> 0) then
      begin
        SetLength(User, UserSize);
        SetLength(Domain, DomainSize);
        if LookupAccountSid(nil, ptiUser.User.Sid, PChar(User), UserSize,
          PChar(Domain), DomainSize, snu) then
        begin
          Result := True;
          User := StrPas(PChar(User));
          Domain := StrPas(PChar(Domain));
        end;
      end;

      if bSuccess then
      begin
        FreeMem(ptiUser);
      end;
    end;
    CloseHandle(ProcessHandle);
  end;
end;

然后我编写了一个获取当前Windows用户名的函数(它使用GetUserName):

const
  UNLEN = 256; // Maximum user name length

function GetWindowsUsername: string;
var
  UserName : string;
  UserNameLen : Dword;
begin
  UserNameLen := UNLEN;
  SetLength(UserName, UserNameLen) ;
  if GetUserName(PChar(UserName), UserNameLen)
  then Result := Copy(UserName, 1, UserNameLen - 1)
  else Result := '';
end;

以下函数返回由属于当前用户的所有进程ID组成的数组(请注意,进程按进程名称进行过滤):

uses
  TlHelp32;

type
  TCardinalArray = array of Cardinal;

function GetCurrentUserPIDs(const AProcessName : string) : TCardinalArray;
var
  ContinueLoop: boolean;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
  UserName : string;
  DomainName : string;
  CurrentUser : string;
begin
  CurrentUser := GetWindowsUsername();

  SetLength(Result, 0);
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  while(ContinueLoop) do
  begin
    if(SameText(FProcessEntry32.szExeFile, AProcessName)) then
    begin
      if(GetUserAndDomainFromPID(FProcessEntry32.th32ProcessID, UserName, DomainName)) then
      begin
        if(UserName = CurrentUser) then
        begin
          SetLength(Result, Length(Result) + 1);
          Result[Length(Result) - 1] := FProcessEntry32.th32ProcessID;
        end;
      end;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;