c++服务-模拟用户登录
C++ Service - Simulate User Login
我在实验室的所有计算机上都运行了一个服务,并且需要能够同时登录到所有计算机。
所有的电脑都有相同的用户名,所以这不是问题。但是我很难找到一种方法来编程地启动登录。我读过LogonUser()
和它的同类产品,但它们似乎没有我需要的功能。有没有人有任何建议,我怎么能做到这一点,从一个c++服务?
唯一直接且受支持的方法是使用自动标记功能。它的主要缺点是需要重新启动机器。
以下是我使用的代码(注意,我们的帐户域"scms"是硬编码的,所以你需要更改该位):#define _WIN32_WINNT 0x0601
#include <windows.h>
#include <Ntsecapi.h>
#include <stdio.h>
#include <wchar.h>
void setAutologon(void);
void clearAutologon(void);
WCHAR username[128];
WCHAR password[128];
int main(int argc, char ** argv)
{
if (argc == 2 && _stricmp(argv[1], "-clear") == 0)
{
clearAutologon();
return 0;
}
if (argc != 3)
{
printf("Syntax: autologon username passwordn");
return 1;
}
swprintf_s(username, _countof(username), L"%hs", argv[1]);
swprintf_s(password, _countof(password), L"%hs", argv[2]);
setAutologon();
return 0;
}
void fail(char * errmsg, DWORD err)
{
// Oops. It didn't work.
printf(errmsg, err);
if (err == 0) err = 1;
exit(err);
}
void storePassword(BOOL store_password)
{
LSA_OBJECT_ATTRIBUTES loa;
LSA_HANDLE lh;
LSA_UNICODE_STRING name;
static const wchar_t name_buffer[] = L"DefaultPassword";
LSA_UNICODE_STRING data;
DWORD dw;
loa.Length = sizeof(loa);
loa.RootDirectory = NULL;
loa.ObjectName = NULL;
loa.Attributes = 0;
loa.SecurityDescriptor = NULL;
loa.SecurityQualityOfService = NULL;
if ((dw = LsaOpenPolicy(NULL, &loa, POLICY_CREATE_SECRET, &lh)) != 0) fail("Error %u opening LSA policy.", LsaNtStatusToWinError(dw));
name.Buffer = (wchar_t *)name_buffer;
name.MaximumLength = name.Length = sizeof(name_buffer) - sizeof(*name_buffer);
if (!store_password)
{
if ((dw = LsaStorePrivateData(lh, &name, NULL)) != 0) fail("Error %u clearing stored password.", LsaNtStatusToWinError(dw));
return;
}
data.Buffer = password;
data.MaximumLength = data.Length = wcslen(password) * sizeof(*password);
if ((dw = LsaStorePrivateData(lh, &name, &data)) != 0) fail("Error %u storing password.", LsaNtStatusToWinError(dw));
LsaClose(lh);
return;
}
void setAutologon()
{
LONG i;
HKEY h;
i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", 0, KEY_WOW64_64KEY | KEY_SET_VALUE, &h);
if (i != ERROR_SUCCESS) fail("Unable to open Winlogon subkey (error %u).", i);
i = RegSetValueEx(h, L"DefaultUserName", 0, REG_SZ, (CONST BYTE *)username, (wcslen(username)+1)*2);
if (i != ERROR_SUCCESS) fail("Unable to set default logon user name (error %u).", i);
storePassword(TRUE);
i = RegSetValueEx(h, L"DefaultDomainName", 0, REG_SZ, (CONST BYTE *)L"scms", 10);
if (i != ERROR_SUCCESS) fail("Unable to set default domain name (error %u).", i);
i = RegSetValueEx(h, L"AutoAdminLogon", 0, REG_SZ, (CONST BYTE *)L"1", 2);
if (i != ERROR_SUCCESS) fail("Unable to set automatic logon flag (error %u).", i);
i = RegSetValueEx(h, L"ForceAutoLogon", 0, REG_SZ, (CONST BYTE *)L"1", 2);
if (i != ERROR_SUCCESS) fail("Unable to set forced automatic logon flag (error %u).", i);
}
void clearAutologon(void)
{
LONG i;
HKEY h;
i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", 0, KEY_WOW64_64KEY | KEY_SET_VALUE, &h);
if (i != ERROR_SUCCESS) fail("Unable to open Winlogon subkey (error %u).", i);
i = RegSetValueEx(h, L"DefaultUserName", 0, REG_SZ, "", 1);
if (i != ERROR_SUCCESS) fail("Unable to set default logon user name (error %u).", i);
storePassword(FALSE);
// In case the automatic logon was set by the previous version of rpwd or by
// some other means, we clear the registry setting for DefaultPassword as well.
i = RegDeleteValue(h, L"DefaultPassword");
if (i != ERROR_SUCCESS && i != ERROR_FILE_NOT_FOUND) fail("Unable to remove default logon password (error %u).", i);
i = RegDeleteValue(h, L"ForceAutoLogon");
if (i != ERROR_SUCCESS && i != ERROR_FILE_NOT_FOUND) fail("Unable to remove force logon flag (error %u).", i);
i = RegSetValueEx(h, L"AutoAdminLogon", 0, REG_SZ, (CONST BYTE *)"0", 2);
if (i != ERROR_SUCCESS) fail("Unable to clear automatic logon flag (error %u).", i);
}
我使用psexec
(可从MS网站获得)在所有实验机器上运行代码,并使用psshutdown
(同上)重新启动它们。一旦他们开始登录过程,你可以清除自动登录。
毫无疑问,你可以很容易地将同样的方法应用到服务中。
如果希望避免重新启动,则需要实现一个凭据提供程序。上次我研究这个问题时,文档少得令人沮丧,但这可能已经有所改善。您可能还对pGINA感兴趣,它是一个开放源代码的凭证提供程序,可以作为一个有用的示例。(或者,据我所知,可能已经包含了您想要的功能!)
相关文章:
- 如何在 c++ 中将密码和用户名保存到 .txt 文件中.如果用户尝试登录,我仍然希望能够检索它们
- Win7 C++ - 从以用户身份登录的服务启动可执行文件的问题
- 用户注销/登录后,创建托盘图标时出现罕见错误
- 是否有任何 C 函数或 API 来获取当前登录用户下运行的进程列表
- 如何从 Windows 上的服务在未登录用户的桌面上启动应用程序
- 获取 Windows 系统已加入 Azure AD 时登录用户的 UserPrincipalName
- 加密用户数据,而不会丢失安卓应用程序中的登录用户
- 如何检查用户登录到Windows的时间
- 嗨,我正在尝试编码一个允许用户在Visual C 中登录的按钮,程序正在运行,但表单对话框未显示
- 如何从非管理员用户获取当前登录的用户名、域名和用户 sid
- 我如何将登录的用户登录到当前会话中的域用户
- C++检查是否有用户登录到Windows7
- 如何添加基于时间的限制以阻止Windows用户登录
- 在C++中跟踪用户登录的可行性
- 应用程序是不可见的,如果没有任何用户登录从任务调度程序启动
- c++服务-模拟用户登录
- 在Linux/Mac上使用c++检测/等待用户登录
- C++:如何在 Windows 凭据管理器中以编程方式创建本地用户登录凭据,以便"runas /savecred"可以使用它?
- 如何在用户登录/关闭或PC进入睡眠/休眠时正确通知c++ Windows服务
- 如何在多个用户登录Windows时获取活动用户