我正在尝试让服务在 Windows 中打开的 session 中创建进程。 我有这个代码:
sessionId =WTSGetActiveConsoleSessionId();
if (WTSQueryUserToken(sessionId,&dummy)) {
if (!DuplicateTokenEx(dummy, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &token)) {
CloseHandle(dummy);
return false;
}
CloseHandle(dummy);
// Create process for user with desktop
myfile = fopen("c:\\temp\\test123.txt", "a");
fprintf(myfile, "before create!!!!\n");
fclose(myfile);
if (!CreateProcessAsUser(token, NULL,NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { // The "new console" is necessary. Otherwise the process can hang our main process
CloseHandle(token);
myfile = fopen("c:\\temp\\test123.txt", "a");
fprintf(myfile, " create failed!\n");
fclose(myfile);
return false;
}
CloseHandle(token);
}
else {
myfile = fopen("c:\\temp\\test123.txt", "a");
fprintf(myfile, "Dummy fail\n");
fprintf(myfile, "last error is %d \n", GetLastError());
fclose(myfile);
}
//int ret = CreateProcess(FILE_EXEC, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
如果我在服务安装中使用最后一行(注释),一切正常,因为它在安装服务时运行,所以它发生在用户 session 中,但是当我想让服务执行它时,它失败了, sessionId 没问题,失败开始于:
if (WTSQueryUserToken(sessionId,&dummy)) {
我知道 WTSQueryUserToken 是一个应该从服务运行的函数,sessionid 是 1(它是来自 cmd 检查的真实数字)并且假人应该在它之后保存用户 token 但由于某种原因它失败了。 ...有什么想法吗?
最佳答案
我在自己的服务中使用了与您类似的代码,并且运行良好。有些事情需要考虑到您显示的代码没有做:
调用
WTSQueryUserToken()
时,您必须确保您的服务进程启用了SE_TCB_NAME
权限。为此使用AdjustTokenPrivileges()
。WTSGetActiveConsoleSessionId()
返回的 session ID 可能不是您需要运行衍生进程的正确 session !它返回连接到本地计算机的物理控制台(屏幕/键盘/鼠标)的 session ID(如果有)。该 session 可能显示安全的 WinLogon 桌面,这意味着实际上没有用户登录到物理机器,因此在该 session ID 上调用WTSQueryUserToken()
将失败并返回ERROR_NO_TOKEN
错误。例如,用户可以通过远程桌面连接登录,在这种情况下,该连接将在与控制台不同的 session 中运行。如果您希望生成的进程在有用户登录的 session 中运行,您需要使用WTSEnumerateSessions()
来查找处于WTSActive
状态的 session 。即使这样,WTSQueryUserToken()
也可能不会返回 token ,具体取决于用户的登录方式,因此您需要在找到的每个事件 session 上调用WTSQueryUserToken()
直到你找到一个成功给你 token 的人。调用
DuplicateTokenEx()
时,使用SecurityIdentification
而不是SecurityDelegation
。调用
CreateProcessAsUser()
时,您可以先调用CreateEnvironmentBlock()
来创建适合该特定用户的环境,然后将该指针传递给CreateProcessAsUser()
。否则,生成的进程将改为使用您的服务环境。此步骤是可选的,具体取决于衍生应用的特定需求。
关于windows - 从服务在用户 session 中创建进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26913172/