C ++从进程中获取用户名

时间:2010-04-21 19:49:59

标签: c++ winapi process

我有一个带

的流程句柄
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, THE_PROCESS_ID);

如何获取正在运行该进程的用户的用户名?

我使用的是非托管代码(没有.NET)。

4 个答案:

答案 0 :(得分:20)

使用OpenProcessToken获取令牌(显然),然后GetTokenInformation使用TokenOwner标志获取所有者的SID。然后,您可以使用LookupAccountSid获取用户名。

答案 1 :(得分:5)

如果WMI不是一个选项,那么使用下面的 GetUserFromProcess ,它将进程ID作为输入参数并返回用户名和域:

#include <comdef.h>
#define MAX_NAME 256
BOOL GetLogonFromToken (HANDLE hToken, _bstr_t& strUser, _bstr_t& strdomain) 
{
   DWORD dwSize = MAX_NAME;
   BOOL bSuccess = FALSE;
   DWORD dwLength = 0;
   strUser = "";
   strdomain = "";
   PTOKEN_USER ptu = NULL;
 //Verify the parameter passed in is not NULL.
    if (NULL == hToken)
        goto Cleanup;

       if (!GetTokenInformation(
         hToken,         // handle to the access token
         TokenUser,    // get information about the token's groups 
         (LPVOID) ptu,   // pointer to PTOKEN_USER buffer
         0,              // size of buffer
         &dwLength       // receives required buffer size
      )) 
   {
      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 
         goto Cleanup;

      ptu = (PTOKEN_USER)HeapAlloc(GetProcessHeap(),
         HEAP_ZERO_MEMORY, dwLength);

      if (ptu == NULL)
         goto Cleanup;
   }

    if (!GetTokenInformation(
         hToken,         // handle to the access token
         TokenUser,    // get information about the token's groups 
         (LPVOID) ptu,   // pointer to PTOKEN_USER buffer
         dwLength,       // size of buffer
         &dwLength       // receives required buffer size
         )) 
   {
      goto Cleanup;
   }
    SID_NAME_USE SidType;
    char lpName[MAX_NAME];
    char lpDomain[MAX_NAME];

    if( !LookupAccountSid( NULL , ptu->User.Sid, lpName, &dwSize, lpDomain, &dwSize, &SidType ) )                                    
    {
        DWORD dwResult = GetLastError();
        if( dwResult == ERROR_NONE_MAPPED )
           strcpy (lpName, "NONE_MAPPED" );
        else 
        {
            printf("LookupAccountSid Error %u\n", GetLastError());
        }
    }
    else
    {
        printf( "Current user is  %s\\%s\n", 
                lpDomain, lpName );
        strUser = lpName;
        strdomain = lpDomain;
        bSuccess = TRUE;
    }

Cleanup: 

   if (ptu != NULL)
      HeapFree(GetProcessHeap(), 0, (LPVOID)ptu);
   return bSuccess;
}

HRESULT GetUserFromProcess(const DWORD procId,  _bstr_t& strUser, _bstr_t& strdomain)
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,procId); 
    if(hProcess == NULL)
        return E_FAIL;
    HANDLE hToken = NULL;

    if( !OpenProcessToken( hProcess, TOKEN_QUERY, &hToken ) )
    {
        CloseHandle( hProcess );
        return E_FAIL;
    }
    BOOL bres = GetLogonFromToken (hToken, strUser,  strdomain);

    CloseHandle( hToken );
    CloseHandle( hProcess );
    return bres?S_OK:E_FAIL;
}

答案 2 :(得分:1)

WMI可能是阻力最小的路径。您还应该能够使用OpenProcessToken获取令牌,然后使用GetTokenInformation获取所有者的SID。然后,您可以将SID转换为用户名。

答案 3 :(得分:0)

WMI应该可以告诉你这些信息。 否则你需要依赖ntdll.dll中无证件的乐趣。似乎其他人找到了不使用ntdll.dll的解决方案 - 使用它们而不是未记录的东西。