将正在运行的程序的用户名与登录到Windows的用户名进行比较

Compare username of running program to username logged into Windows

本文关键字:用户 Windows 比较 登录 程序 运行      更新时间:2023-10-16

我试图实现一个程序来控制登录计算机的用户和运行程序的用户的名称是否相同,但我认为我做错了什么。用户名登录的名称有效,但不是获取运行程序的用户的名称。

#include <Windows.h>
#include <iostream>
#include <stdlib.h>
#include <Lmcons.h>
#include <tchar.h>
#include <stdio.h>
#define INFO_BUFFER_SIZE 32767
using namespace std;
void Test() {
WCHAR  UsernameSSR[INFO_BUFFER_SIZE];
TCHAR  UsernameWindows[INFO_BUFFER_SIZE];
DWORD  bufCharCountWindows = INFO_BUFFER_SIZE;
DWORD  bufCharCountSSR = INFO_BUFFER_SIZE;
GetUserName(UsernameWindows, &bufCharCountWindows); 
GetUserNameW(UsernameSSR, &bufCharCountSSR);
cout << UsernameWindows << " and " << UsernameSSR;
return;
}

GetUserName()只是一个映射到GetUserNameA()(ANSI(或GetUserNameW()(Unicode(的预处理器宏,具体取决于您的项目设置。 无论哪种方式,GetUserName(A|W)都会返回当前与调用线程关联的用户名,在您的示例中,该用户名也是用于运行程序的用户名。 没有GetUserNameA()GetUserNameW()混合在一起会得到你想要的结果,因为它们将返回相同的用户名,只是在不同的字符编码中。

要获取登录到Windows本身的用户名,您需要一个不同的功能,例如WTSQuerySessionInformation()(A或W变体(,例如:

#include <iostream>
#include <Windows.h>
#include <wtsapi32.h>
#include <Lmcons.h>
void Test()
{
WCHAR  UsernameSSR[UNLEN+1];
DWORD  bufCharCountSSR = UNLEN+1;
if (GetUserNameW(UsernameSSR, &bufCharCountSSR)) 
std::wcout << L"UsernameSSR: " << UsernameSSR << std::endl;
else
std::wcout << L"Error getting UserNameSSR" << std::endl;
// alternatively, use GetUserNameExW() instead...
LPWSTR UsernameWindows;
DWORD  bufByteCountWindows;
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSUserName, &UsernameWindows, &bufByteCountWindows))
{
LPWSTR Domain;
DWORD bufByteCountDomain;
std::wcout << L"UsernameWindows: ";
if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSDomainName, &Domain, &bufByteCountDomain))
{
if (*Domain)
std::wcout << Domain << L"\";
WTSFreeMemory(Domain);
}
std::wcout << UsernameWindows << std::endl;
WTSFreeMemory(UsernameWindows);
}
else
std::wcout << L"Error getting UserNameWindows" << std::endl;
// alternatively, query WTSQuerySessionInformation() for WTSSessionInfo, which
// returns both Domain and UserName in a single call, amongst other pieces of info...
}

话虽如此,比较用户名字符串并不是确定程序是否由登录到 Windows 的同一用户运行的最佳方法。

例如,另一种方法是获取运行程序的用户的安全标识符(SID(,然后将其与使用EqualSid()登录到Windows的用户的SID进行比较。

获取调用进程的 SID 非常简单:可以使用GetCurrentProcessId()OpenProcessToken(TOKEN_QUERY)GetTokenInformation(TokenUser)

但是,获取已登录的 Windows 会话的 SID 有点棘手。 您可以:

  • 获取登录用户的会话 ID,例如生成程序的进程的ProcessIdToSessionId()QueryTokenInformation(TokenSessionId)(若要查找父进程 ID,请使用CreateToolhelp32Snapshot()Process32First()Process32Next()(,然后将该会话 ID 传递给WTSQueryUserToken(),然后从该令牌查询 SID。 问题是WTSQueryUserToken()只能从LocalSystem帐户下运行的服务调用,因此您必须编写这样的服务并通过您选择的 IPC 机制委托给它。

  • 如上所述检索用户会话的域\用户名,然后使用 WMI 查询该特定用户的Win32_UserAccount表并读取其Sid属性,然后使用ConvertStringSidToSid()将 SID 解析为其二进制形式。

您在第一个参数 (name之后错过了,GetUserNameA((LPSTR)name(LPDWORD) & size)

另外,你为什么使用GetUserName而不是GetUserNameW?在某些情况下GetUserName将与GetUserNameA相同,因此,如果您尝试获得差异,请直接写GetUserNameW