参考:
- GetUserNameA function (winbase.h) - Win32 apps | Microsoft Docs
- Getting System Information - Win32 apps | Microsoft Docs
- WINDOWS-API:取得当前用户账户名-GetUserName - CPYER - 博客园
- 获取windows当前登录的用户名_kevin的博客-CSDN博客_windows用户名
公司项目有个要求,就是要获取windows当前登录的用户名作为安装路径的一部分,于是百度很容易地找到了GetUserName这个windows提供的方法。
本以为一切就是这么简单,后来才发现,GetUserName返回的只是当前线程关联的用户名。
Retrieves the name of the user associated with the current thread.
也就是说,这个用户名就是任务管理器中显示的用户名。如果这个线程是以system权限运行的,返回的就是system,而不是windows当前登录的用户名!
感谢获取windows当前登录的用户名_kevin的博客-CSDN博客_windows用户名这位博主的文章给了我很大的帮助!
文章中的法1还是会返回system,这里采用文章中的法2:获取explorer.exe的用户名,但是NetUserGetInfo会返回失败,导致一度认为哪里有问题,其实LookupAccountSid就已经获取到用户名了。这里改进下代码,同时优化下获取explorer.exe的方式,无需像原来那样通过遍历的方式找到explorer.exe。(而且遍历的方式也有一个问题,就是多个用户使用同一台机的时候,切换到其他用户的桌面,找到的explorer.exe,不一定是当前登录的用户的,还可能是其他已登录的用户的!)
#include <windows.h>
#include <string>
#include <algorithm>
bool Get_LogUser(std::wstring& wsName)
{
HWND hwnd = ::GetShellWindow();
if (nullptr == hwnd) {
return false;
}
DWORD dwProcessID = 0;
GetWindowThreadProcessId(hwnd, &dwProcessID);
if (0 == dwProcessID) {
return false;
}
HANDLE hProc = NULL;
HANDLE hToken = NULL;
TOKEN_USER* pTokenUser = NULL;
// Open the process with PROCESS_QUERY_INFORMATION access
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
if (hProc == NULL)
{
return false;
}
if (!OpenProcessToken(hProc, TOKEN_QUERY, &hToken))
{
return false;
}
DWORD dwNeedLen = 0;
GetTokenInformation(hToken, TokenUser, NULL, 0, &dwNeedLen);
if (dwNeedLen > 0)
{
pTokenUser = (TOKEN_USER*)new BYTE[dwNeedLen];
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwNeedLen, &dwNeedLen))
{
return false;
}
}
else
{
return false;
}
SID_NAME_USE sn;
TCHAR szDomainName[MAX_PATH];
DWORD dwDmLen = MAX_PATH;
WCHAR wstrName[MAX_PATH] = {};
DWORD nNameLen = MAX_PATH;
LookupAccountSid(NULL, pTokenUser->User.Sid, wstrName, &nNameLen,
szDomainName, &dwDmLen, &sn);
wsName = wstrName;
if (hProc)
::CloseHandle(hProc);
if (hToken)
::CloseHandle(hToken);
if (pTokenUser)
delete[](char*)pTokenUser;
//LPUSER_INFO_3 bufptr = NULL;
//NET_API_STATUS t3;
//t3 = NetUserGetInfo(0, wstrName, 3, (LPBYTE*)&bufptr);
//if (t3 != NERR_Success)
//{
// return;
//}
//全名不为空,就使用用户名的全名,为空就使用用户名
//CString strFullName = bufptr->usri3_full_name;
//if (strFullName.IsEmpty())
//{
// csName = bufptr->usri3_name;
//}
//else
//{
// csName = bufptr->usri3_full_name;
//}
//NetApiBufferFree(bufptr);
//bufptr = NULL;
return true;
}
bool GetCurrentProcessUser(std::wstring& wstrUserName)
{
bool bRet = false;
wstrUserName.clear();
try
{
DWORD dwSize = MAX_PATH;
TCHAR* pszName = new TCHAR[dwSize];
// Get and display the user name.
bRet = GetUserName(pszName, &dwSize);
if (!bRet)
{
// If lpBuffer is too small, the function failsand GetLastError returns ERROR_INSUFFICIENT_BUFFER.
// This parameter receives the required buffer size, including the terminating null character.
delete[] pszName;
pszName = new TCHAR[dwSize];
bRet = GetUserName(pszName, &dwSize);
}
if (pszName != NULL)
{
wstrUserName = pszName;
delete[] pszName;
}
std::transform(wstrUserName.begin(), wstrUserName.end(), wstrUserName.begin(), std::tolower);
if (!wstrUserName.compare(L"system"))
{
wstrUserName.clear();
bRet = Get_LogUser(wstrUserName);
}
}
catch (...)
{
bRet = false;
}
return bRet;
}
void main()
{
std::wstring wstrUserName;
GetCurrentProcessUser(wstrUserName);
}