【问题标题】:C++ Get Username From ProcessC++ 从进程中获取用户名
【发布时间】:2011-02-10 18:44:57
【问题描述】:

我有一个进程句柄

HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, THE_PROCESS_ID);

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

我正在使用非托管代码(没有 .NET)。

【问题讨论】:

    标签: c++ winapi process


    【解决方案1】:

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

    【讨论】:

    • 效果很好。我不得不使用 TokenUser 来获取用户名。 TokenOwner 正在返回组名(管理员)。
    【解决方案2】:

    如果 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;
    }
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • ntdll.dll 中未记录的内容是未记录的。
        • @Stewart:我同意。这就是我没有详细说明的原因。
        猜你喜欢
        • 2011-06-15
        • 2020-07-28
        • 2017-10-15
        • 1970-01-01
        • 1970-01-01
        • 2015-06-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多