2016-11-18 82 views
1

我正在尝试获取属于当前用户的进程的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; 
+0

http://stackoverflow.com/questions/559356/how-do-i-get-the-sid-session-of -an-AR bitrary-process/14845528 –

+0

@SertacAkyuz:谢谢,如果我明白了,我应该用'OpenProcess'。如果可能的话,我会避免使用该函数来避免访问被拒绝的问题[这里](http://stackoverflow.com/questions/40630528/is-possible-to-get-full-file-name-of-a-过程换其-I-具有-NO-权限)。有其他方法吗?任务管理器显示进程所属的用户 – ExDev

+2

我认为您可以将OpenProcessToken与GetTokenInformation一起使用来验证进程是否属于运行应用程序的同一用户。任务管理器只在提升时报告用户名。否则,当前用户不拥有的进程对于用户名显示为空白。无论如何,你无法避免你的进程无法访问的access_denied。 –

回答

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;