我使用以下方法来获取进程(指定进程ID)的所属用户名,但我调试时只能成功获取到 SYSTEM 和 Administrator(我的登陆用户名) 这两种用户名,而无法获取到 LOCAL SERVICE、NETWORK SERVICE 这两种用户名,并发现失败的地方是在用 OpenProcessToken 打开进程令牌这一步。PS: 本程序已经首先赋予了 SeDebugPrivilege 访问权限,所以在用 OpenProcess 打开进程句柄时都能通过。问题代码如下,急待解决,望高手们相助!Private Declare Function LookupAccountSid Lib "advapi32.dll" Alias "LookupAccountSidA" (ByVal lpSystemName As String, ByVal SID As Long, ByVal name As String, cbName As Long, ByVal ReferencedDomainName As String, cbReferencedDomainName As Long, peUse As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal TokenInformationClass As Long, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPrivate Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_READ = 16
Private Const SECURITY_BUILTIN_DOMAIN_RID = &H20&
Private Const SECURITY_NT_AUTHORITY = &H5
Private Const DOMAIN_ALIAS_RID_USERS = &H221
Private Const TOKEN_READ = &H20008
Private Const TokenUser = 1Private Type SID_IDENTIFIER_AUTHORITY
Value(6) As Byte
End TypePrivate Type SID_AND_ATTRIBUTES
SID As Long
Attributes As Long
End TypePrivate Type TOKEN_USER
User As SID_AND_ATTRIBUTES
SID(500) As Byte
End TypePrivate Function GetPrcUserName(ByVal pID As Long) As String Dim hProcessID As Long
Dim hToken As Long
Dim res As Long
Dim cbBuff As Long
Dim tiLen As Long
Dim TU As TOKEN_USER
Dim cnt As Long
Dim sAcctName2 As String
Dim cbAcctName As Long
Dim sDomainName As String
Dim cbDomainName As Long
Dim peUse As Long
Dim barr() As Byte
hProcessID = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, pID)
If hProcessID <> 0 Then
If OpenProcessToken(hProcessID, TOKEN_READ, hToken) = 1 Then '这一步可能失败
res = GetTokenInformation(hToken, TokenUser, ByVal 0, tiLen, cbBuff)
If res = 0 And cbBuff > 0 Then
tiLen = cbBuff
If cbBuff > Len(TU) Then Exit Function
res = GetTokenInformation(hToken, TokenUser, TU, tiLen, cbBuff)
If res = 1 And tiLen > 0 Then
sAcctName2 = Space$(255)
sDomainName = Space$(255)
cbAcctName = 255
cbDomainName = 255
res = LookupAccountSid(vbNullString, TU.User.SID, sAcctName2, cbAcctName, sDomainName, cbDomainName, peUse)
GetPrcUserName = Replace(Trim(sAcctName2), Chr(0), "")
End If
End If
Else
GetPrcUserName = "OpenProcessToken 失败"
End If
If hToken Then CloseHandle hToken
CloseHandle hProcessID
End If
End Function
Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
Private Declare Function GetTokenInformation Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal TokenInformationClass As Long, TokenInformation As Any, ByVal TokenInformationLength As Long, ReturnLength As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As LongPrivate Const PROCESS_QUERY_INFORMATION = 1024
Private Const PROCESS_VM_READ = 16
Private Const SECURITY_BUILTIN_DOMAIN_RID = &H20&
Private Const SECURITY_NT_AUTHORITY = &H5
Private Const DOMAIN_ALIAS_RID_USERS = &H221
Private Const TOKEN_READ = &H20008
Private Const TokenUser = 1Private Type SID_IDENTIFIER_AUTHORITY
Value(6) As Byte
End TypePrivate Type SID_AND_ATTRIBUTES
SID As Long
Attributes As Long
End TypePrivate Type TOKEN_USER
User As SID_AND_ATTRIBUTES
SID(500) As Byte
End TypePrivate Function GetPrcUserName(ByVal pID As Long) As String Dim hProcessID As Long
Dim hToken As Long
Dim res As Long
Dim cbBuff As Long
Dim tiLen As Long
Dim TU As TOKEN_USER
Dim cnt As Long
Dim sAcctName2 As String
Dim cbAcctName As Long
Dim sDomainName As String
Dim cbDomainName As Long
Dim peUse As Long
Dim barr() As Byte
hProcessID = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, pID)
If hProcessID <> 0 Then
If OpenProcessToken(hProcessID, TOKEN_READ, hToken) = 1 Then '这一步可能失败
res = GetTokenInformation(hToken, TokenUser, ByVal 0, tiLen, cbBuff)
If res = 0 And cbBuff > 0 Then
tiLen = cbBuff
If cbBuff > Len(TU) Then Exit Function
res = GetTokenInformation(hToken, TokenUser, TU, tiLen, cbBuff)
If res = 1 And tiLen > 0 Then
sAcctName2 = Space$(255)
sDomainName = Space$(255)
cbAcctName = 255
cbDomainName = 255
res = LookupAccountSid(vbNullString, TU.User.SID, sAcctName2, cbAcctName, sDomainName, cbDomainName, peUse)
GetPrcUserName = Replace(Trim(sAcctName2), Chr(0), "")
End If
End If
Else
GetPrcUserName = "OpenProcessToken 失败"
End If
If hToken Then CloseHandle hToken
CloseHandle hProcessID
End If
End Function
BOOL WTSEnumerateProcesses(
HANDLE hServer,
DWORD Reserved,
DWORD Version,
PWTS_PROCESS_INFO* ppProcessInfo,
DWORD* pCount
);
照您的提示,我用 WTSEnumerateProcesses 解决了问题!谢谢!