如何擷取Windows系統登陸使用者名稱

來源:互聯網
上載者:User

如何擷取Windows系統登陸使用者名稱
關鍵字 :擷取登陸使用者名稱 GetUserName WTSQuerySessionInformation
    一般用 GetUserName(或 GetUserNameEx )函數可得到當前登陸登陸使用者名稱(但不總會得到,下面會分析),此系統函數在Win95、WinNT 及以後所有作業系統中都可用。代碼如下:
    BOOL CSecurityTool::GetCurrProcessUser(CString& strName)
    {
        BOOL bRet(TRUE);
        strName = _T("");
        DWORD dwSize = MAX_PATH;
        TCHAR *pszName = new TCHAR[dwSize];
        if (!GetUserName(pszName, &dwSize))
        {
            delete[] pszName;
            pszName = new TCHAR[dwSize];
            bRet = GetUserName(pszName, &dwSize);
         }
        strName = pszName;
        delete[] pszName;
        return bRet;
    }
     此函數目的準確來說是擷取當前線程的使用者名稱(MSDN語:retrieves the user name of the current thread)。如果是NT service(NT服務程式)將此進程啟動,得到的結果是NT Service進程的使用者名稱,即“SYSTEM”,而不是登陸使用者名稱;同理,如果此進程是通過CreateProcessAsUser建立的,GetUserName擷取的使用者將是“AsUser”的使用者名稱。另外,如果當前線程正impersonate其他使用者環境(用函數ImpersonateLoggedOnUser可達到此目的),它擷取的將是其他使用者名稱。因此,此函數只能在特定環境中才可以擷取登陸使用者名稱。那如何不因進程本身運行環境的不同,而準確地擷取登陸使用者名稱呢? 我們首先看看Windows XP作業系統,它提供了WTSQuerySessionInformation函數,這個函數可以擷取會話(session)相關資訊,其中一個用 途是擷取會話的登陸使用者。代碼如下:
     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即可;否則,需要採用後面的兩種方法,當然,在使用前需要判斷一下作業系統的類型。

    歡迎諸位與大家分享其他方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.