windows - 从服务在用户 session 中创建进程

标签 windows winapi service

我正在尝试让服务在 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 但由于某种原因它失败了。 ...有什么想法吗?

最佳答案

我在自己的服务中使用了与您类似的代码,并且运行良好。有些事情需要考虑到您显示的代码没有做:

  1. 调用 WTSQueryUserToken() 时,您必须确保您的服务进程启用了 SE_TCB_NAME 权限。为此使用 AdjustTokenPrivileges()

  2. WTSGetActiveConsoleSessionId() 返回的 session ID 可能不是您需要运行衍生进程的正确 session !它返回连接到本地计算机的物理控制台(屏幕/键盘/鼠标)的 session ID(如果有)。该 session 可能显示安全的 WinLogon 桌面,这意味着实际上没有用户登录到物理机器,因此在该 session ID 上调用 WTSQueryUserToken() 将失败并返回 ERROR_NO_TOKEN错误。例如,用户可以通过远程桌面连接登录,在这种情况下,该连接将在与控制台不同的 session 中运行。如果您希望生成的进程在有用户登录的 session 中运行,您需要使用 WTSEnumerateSessions() 来查找处于 WTSActive 状态的 session 。即使这样,WTSQueryUserToken() 也可能不会返回 token ,具体取决于用户的登录方式,因此您需要在找到的每个事件 session 上调用 WTSQueryUserToken() 直到你找到一个成功给你 token 的人。

  3. 调用 DuplicateTokenEx() 时,使用 SecurityIdentification 而不是 SecurityDelegation

  4. 调用 CreateProcessAsUser() 时,您可以先调用 CreateEnvironmentBlock() 来创建适合该特定用户的环境,然后将该指针传递给CreateProcessAsUser()。否则,生成的进程将改为使用您的服务环境。此步骤是可选的,具体取决于衍生应用的特定需求。

关于windows - 从服务在用户 session 中创建进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26913172/

相关文章:

Windows API 函数

c++ - 在 winapi 中将 null 传递给 CreateCompatibleDC() 时返回什么

c++ - 检查 Internet Explorer 保护模式

android - 通过提供一个扩展 Thread 并覆盖其 run() 方法的新类来实现 Thread

在命中 "SyntaxError: invalid syntax"之后,Python 在 Cygwin 下给出 "return"但在 CMD 中没有给出?

c++ - 如何使用某个驱动器中打开的文件夹关闭 Windows 资源管理器窗口

c++ - 如何拦截消息: "WM_QUIT || WM_DESTROY || WM_CLOSE" WinAPI

c# - 安装没有模板的服务

c# - .NET Windows 服务从 system32 文件夹而不是安装文件夹执行批处理文件

windows - RegOpenKeyEx/RegGetValue 在存在的键上返回 ERROR_FILE_NOT_FOUND