windows 示例代码:服务调用 CreateProcessAsUser() 我希望进程在用户的会话中运行,而不是会话 0

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7285666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 17:59:17  来源:igfitidea点击:

example code: A service calls CreateProcessAsUser() I want the process to run in the user's session, not session 0

windowswinapiwindows-7windows-servicescreateprocessasuser

提问by kevinwaite

I am seeking example code:

我正在寻找示例代码:

For a service calls CreateProcessAsUser() I want the process to run in the user's session, not session 0

对于服务调用 CreateProcessAsUser() 我希望进程在用户的会话中运行,而不是会话 0

thus far the created process is only running like a service in session 0

到目前为止,创建的进程只是像会话 0 中的服务一样运行

回答by Carey Gregory

This was stripped from some old code that launched a console app from a service. It worked under NT4 but I haven't tested it with a modern version of Windows so can't guarantee it will work as it did on NT4.

这是从一些从服务启动控制台应用程序的旧代码中剥离出来的。它在 NT4 下工作,但我没有用现代版本的 Windows 测试过它,所以不能保证它会像在 NT4 上那样工作。

EDIT: No, that's not going to work as-is. You need to add the code found hereto create a desktop, set the SID, etc.

编辑:不,这不会按原样工作。您需要添加在此处找到的代码以创建桌面、设置 SID 等。

    if (!LogonUser(userId,
                   domain,
                   password,
                   LOGON32_LOGON_INTERACTIVE,
                   LOGON32_PROVIDER_DEFAULT,
                   &hUserToken))
    {
        return GetLastError();
    }

    if (!ImpersonateLoggedOnUser(hUserToken))
    {
        DWORD rc = GetLastError();
        CloseHandle(hUserToken);
        return rc;
    }

    STARTUPINFO             si;
    PROCESS_INFORMATION pi;

    memset(&si, 0, sizeof(si));
    memset(&pi, 0, sizeof(pi));

    si.cb = sizeof(si);

    rc = CreateProcessAsUser(hUserToken,                // user token
                           0,                           // app name
                           "foo.exe",                   // command line
                           0,                           // process attributes
                           0,                           // thread attributes
                           FALSE,                       // don't inherit handles
                           DETACHED_PROCESS,            // flags
                           0,                           // environment block
                           0,                           // current dir
                           &si,                         // startup info
                           &pi);                        // process info gets put here


    if (!rc)
    {
        DWORD rc = GetLastError();
        RevertToSelf();
        CloseHandle(hUserToken);
        return rc;
    }

    RevertToSelf();
    CloseHandle(hUserToken);

    return 0;

回答by Paul Sanders

I know this is an ancient post but I happen to be working on this so here's some code that works for me.

我知道这是一篇古老的帖子,但我碰巧正在研究这个,所以这里有一些对我有用的代码。

Determine the session ID of the currently logged-on user

确定当前登录用户的会话 ID

DWORD GetCurrentSessionId ()
{
    WTS_SESSION_INFO *pSessionInfo;
    DWORD n_sessions = 0;
    BOOL ok = WTSEnumerateSessions (WTS_CURRENT_SERVER, 0, 1, &pSessionInfo, &n_sessions);
    if (!ok)
        return 0;

    DWORD SessionId = 0;

    for (DWORD i = 0; i < n_sessions; ++i)
    {
        if (pSessionInfo [i].State == WTSActive)
        {
            SessionId = pSessionInfo [i].SessionId;
            break;
        }
    }

    WTSFreeMemory (pSessionInfo);
    return SessionId;
}

Launch process as the currently logged-on user

以当前登录的用户身份启动进程

bool LaunchProcess (const char *process_path)
{
    DWORD SessionId = GetCurrentSessioId ();
    if (SessionId == 0)    // no-one logged in
        return false;

    HANDLE hToken;
    BOOL ok = WTSQueryUserToken (SessionId, &hToken);
    if (!ok)
        return false;

    void *environment = NULL;
    ok = CreateEnvironmentBlock (&environment, hToken, TRUE);

    if (!ok)
    {
        CloseHandle (hToken);
        return false;
    }

    STARTUPINFO si = { sizeof (si) } ;
    PROCESS_INFORMATION pi = { } ;
    si.lpDesktop = "winsta0\default";

    // Do NOT want to inherit handles here
    DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT;
    ok = CreateProcessAsUser (hToken, process_path, NULL, NULL, NULL, FALSE,
        dwCreationFlags, environment, NULL, &si, &pi);

    DestroyEnvironmentBlock (environment);
    CloseHandle (hToken);

    if (!ok)
        return false;

    CloseHandle (pi.hThread);
    CloseHandle (pi.hProcess);
    return true;
}