WEB开发网
开发学院软件开发VC 如何获取Windows系统登陆用户名 阅读

如何获取Windows系统登陆用户名

 2006-07-20 11:39:39 来源:WEB开发网   
核心提示: BOOL CSecurityTool::GetLogUserXP(CString& strName){BOOL bRet = FALSE;strName = _T("");//for xp or aboveTCHAR *szLogName = NULL;DWORD dw
BOOL CSecurityTool::GetLogUserXP(CString& strName)
{
  BOOL bRet = FALSE;
  strName = _T("");
  //for xp or above
  TCHAR *szLogName = NULL;
  DWORD dwSize = 0;
  if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
                  WTS_CURRENT_SESSION,
                  WTSUserName,
                  &szLogName,
                  &dwSize))
  {      
    strName = szLogName;
    WTSFreeMemory(szLogName);
    bRet = TRUE;
  }
  return bRet;
}   

如果用户还没有登陆,获取的用户名将为空(譬如在NT service程序中)。虽然MSDN中指明WTSQuerySessionInformation可以在win2000 pro 中使用,但由于安装win2000 professional时,terminal service是没有安装的(除非用特殊方法如第三方工具可以安装terminal service),所以调用此函数会失败,需要寻找其他方法。

再看Win2000:查阅了许多资料,未能发现在Win2000中直接获取登陆用户名的系统函数,看来只有曲线救国了。由于Explorer.exe进程的用户肯定是当前登陆用户,所以获取到它的用户名就等于获取到登陆用户名。具体实现:首先枚举系统所有进程,找到Explorer.exe进程ID,然后通过ID获取此进程的令牌(Token),再获取令牌的用户信息,即为登陆用户名。代码如下:

//获取win2000登陆用户   
BOOL CSecurityTool::GetLogUser2K(CString& strName)
{
  BOOL bRet = FALSE;
  HANDLE hSnapshot = NULL;
  strName = _T("");
  __try
  {
    // Get a snapshot of the processes in the system
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == NULL)
    {      
      __leave;
    }
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    // Find the "System" process
    BOOL fProcess = Process32First(hSnapshot, &pe32);
    while (fProcess)
    {
      if (lstrcmpi(pe32.szExeFile, TEXT("explorer.exe")) == 0)
      {  
        TCHAR szUserName[MAX_PATH];
        if (GetProcessUser(pe32.th32ProcessID, szUserName, MAX_PATH))
        {
          bRet = TRUE;
          strName = szUserName;
        }
        
        break;
      }
      fProcess = Process32Next(hSnapshot, &pe32);
    }
    if (!fProcess)
    {      
      __leave;  // Didn''t find "System" process
    }
  }
  __finally
  {
    // Cleanup the snapshot
    if (hSnapshot != NULL)
      CloseHandle(hSnapshot);
  }
  return bRet;  
}
//获取进程的用户名
BOOL CSecurityTool::GetProcessUser(DWORD dwProcessID, TCHAR *szUserName, DWORD nNameLen)
{
  BOOL fResult = FALSE;
  HANDLE hProc = NULL;
  HANDLE hToken = NULL;
  TOKEN_USER *pTokenUser = NULL;
  
  __try
  {
    // Open the process with PROCESS_QUERY_INFORMATION access
    hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
    if (hProc == NULL)
    {
      __leave;
    }
    fResult = OpenProcessToken(hProc, TOKEN_QUERY, &hToken);
    if(!fResult) 
    {
      __leave;
    }
    
    DWORD dwNeedLen = 0;    
    fResult = GetTokenInformation(hToken,TokenUser, NULL, 0, &dwNeedLen);
    if (dwNeedLen > 0)
    {
      pTokenUser = (TOKEN_USER*)new BYTE[dwNeedLen];
      fResult = GetTokenInformation(hToken,
                     TokenUser,
                     pTokenUser,
                     dwNeedLen,
                     &dwNeedLen);
      if (!fResult)
      {
        __leave;
      }
    }
    else
    {
      __leave;
    }
    SID_NAME_USE sn;
    TCHAR szDomainName[MAX_PATH];
    DWORD dwDmLen = MAX_PATH;
    fResult = LookupAccountSid(NULL,
                  pTokenUser->User.Sid,
                  szUserName,
                  &nNameLen,
                  szDomainName,
                  &dwDmLen,
                  &sn);
  }
  __finally
  {
    if (hProc)
      ::CloseHandle(hProc);
    if (hToken)
      ::CloseHandle(hToken);
    if (pTokenUser)
      delete[] (char*)pTokenUser;
    return fResult;
  }
}   

熟悉win2000系统的同仁肯定会发现此方法存在缺陷:explorer.exe进程可能不存在(被用户kill掉或自己中断了),这时候这个方法就获取不到登陆用户名。但在没有更好方法前,只能将就。

总结

因此,软件中如果需要获取登陆用户名,要根据具体情况选择不同的方法。如果确信自己的进程一定在登陆用户环境下启动,则GetUserName即可;否则,需要采用后面的两种方法,当然,在使用前需要判断一下操作系统的类型。附 :源代码。

欢迎诸位与大家分享其他方法。

上一页  1 2 

Tags:如何 获取 Windows

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接