首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CreateProcessAsUser进程退出-1073741502

CreateProcessAsUser进程退出-1073741502
EN

Stack Overflow用户
提问于 2018-06-01 13:08:40
回答 2查看 2.7K关注 0票数 7

我有一个服务,负责在用户登录和控制台会话连接后启动/监视用户会话中的交互过程。服务被设置为自动启动,因此它在用户登录之前启动并运行。在第一次登录时,所有操作都很好,我可以正确启动/重新启动用户进程。

如果用户签出并重新登录服务,则服务将无法正确启动用户进程。CreateProcessAsUser不返回错误,但一旦用户进程启动,其退出代码为-1073741502 (0xC0000142)。

如果我重新启动服务,那么它再次能够启动用户进程,而不会出现任何错误。

如果需要,我可以发布服务如何创建用户进程的完整来源。

编辑

代码语言:javascript
复制
    try
            {
                //WE ALREADY HAVE A CLIENT ATTACHED , DONT START A NEW ONE
                if (ClientProcessId != null)
                    return;

                var ACTIVE_CONSOLE_SESSION = ListSessions()
                    .Where(SESSION => SESSION.State == WTS_CONNECTSTATE_CLASS.WTSActive)
                    .FirstOrDefault();

                if (ACTIVE_CONSOLE_SESSION == null)
                    return;

                CONSOLE_SESSION_ID = (uint)ACTIVE_CONSOLE_SESSION.Id;

                IntPtr USER_TOKEN = IntPtr.Zero;
                IntPtr ENVIRONMENT = IntPtr.Zero;
                IntPtr LINKED_TOKEN = IntPtr.Zero;

                try
                {
                    try
                    {
                        if (!Wtsapi32.WTSQueryUserToken(CONSOLE_SESSION_ID.Value, out USER_TOKEN))
                            throw new Win32Exception();
                    }
                    catch (Win32Exception wex)
                    {
                        EntryPoint.TryWriteToCacheLog($"{nameof(Wtsapi32.WTSQueryUserToken)} : console session id {CONSOLE_SESSION_ID} error {wex.ErrorCode} , native error {wex.NativeErrorCode}");
                        throw;
                    }

                    try
                    {
                        if (!Userenv.CreateEnvironmentBlock(out ENVIRONMENT, USER_TOKEN, true))
                            throw new Win32Exception();
                    }
                    catch (Win32Exception wex)
                    {
                        EntryPoint.TryWriteToCacheLog($"{nameof(Userenv.CreateEnvironmentBlock)} : error {wex.ErrorCode} , native error {wex.NativeErrorCode}");
                        throw;
                    }

                    try
                    {
                        LINKED_TOKEN = CoreProcess.GetLinkedTokeIfRequiered(USER_TOKEN);
                    }
                    catch (Win32Exception wex)
                    {
                        EntryPoint.TryWriteToCacheLog($"{nameof(CoreProcess.GetLinkedTokeIfRequiered)} : error {wex.ErrorCode} , native error {wex.NativeErrorCode}");
                        throw;
                    }

                    //GET PROCESS PATHS
                    string FILE_NAME = EntryPoint.PROCESS_FULL_FILE_NAME;
                    string WORKING_DIRECTORY = EntryPoint.PROCESS_DIRECTORY;

                    //GET CURRENT COMMAND LINE ARGUMENTS
                    var CMD_ARGS = Environment.GetCommandLineArgs();

                    //FIRST ARGUMENT WILL ALWAYS HAVE FULL PROCESS PATH,OTHER ARGUMENTS ARE OPTIONAL
                    var ARGUMENTS_STRING = CMD_ARGS
                        .Skip(1)
                        .DefaultIfEmpty()
                        .Aggregate((first, next) => ' ' + first + ' ' + next);

                    var ARGUMENTS = new StringBuilder(ARGUMENTS_STRING);

                    var START_INFO = new STARTUPINFO();
                    START_INFO.cb = Marshal.SizeOf(START_INFO);
                    START_INFO.lpDesktop = @"winsta0\default";

                    var PROCESS_INFO = new PROCESS_INFORMATION();
                    uint dwCreationFlags = NORMAL_PRIORITY_CLASS | (int)(PROCESS_CREATE_FLAG.CREATE_NEW_CONSOLE | PROCESS_CREATE_FLAG.CREATE_UNICODE_ENVIRONMENT);

                    try
                    {
                        if (!AdvApi32.CreateProcessAsUser(LINKED_TOKEN,
                            FILE_NAME,
                            ARGUMENTS,
                            IntPtr.Zero,
                            IntPtr.Zero,
                            true,
                            dwCreationFlags,
                            ENVIRONMENT,
                            WORKING_DIRECTORY,
                            ref START_INFO,
                            out PROCESS_INFO))
                            throw new Win32Exception();

                        if (PROCESS_INFO.hThread != IntPtr.Zero)
                        {
                            ClientProcessId = PROCESS_INFO.dwProcessId;
                            ClientSessionId = CONSOLE_SESSION_ID;

                            EntryPoint.TryWriteToCacheLog($"{nameof(AdvApi32.CreateProcessAsUser)} : Created porocess {ClientProcessId} in session {CONSOLE_SESSION_ID}.");
                        }
                    }
                    catch (Win32Exception wex)
                    {
                        EntryPoint.TryWriteToCacheLog($"{nameof(AdvApi32.CreateProcessAsUser)} : error {wex.ErrorCode} , native error {wex.NativeErrorCode}");
                        throw;
                    }
                }
                catch (Win32Exception wex)
                {
                    switch (wex.NativeErrorCode)
                    {
                        case 5:
                        case 1008:

                            tryCount++;
                            if (tryCount >= START_RETRIES)
                                throw;

                            Thread.Sleep(RETRY_WAIT_SPAN);

                            if (DisableCallBacks)
                                return;

                            CreateProcess(tryCount);

                            break;
                        default:
                            throw;
                    }
                }
                catch
                {
                    throw;
                }
                finally
                {
                    Userenv.DestroyEnvironmentBlock(ENVIRONMENT);
                    Kernel32.CloseHandle(USER_TOKEN);
                    if (USER_TOKEN != LINKED_TOKEN)
                        Kernel32.CloseHandle(LINKED_TOKEN);
                }
            }
            catch (Exception ex)
            {
                EntryPoint.TryWriteToCacheLog($"{nameof(CreateProcess)} failed after {tryCount} retries, console seesion id {(CONSOLE_SESSION_ID != null ? CONSOLE_SESSION_ID.ToString() : "Unobtained")}.", ex.ToString());
            }
            finally
            {
                Monitor.Exit(CREATE_LOCK);
            }

  public static TOKEN_ELEVATION_TYPE GetTokenElevationLevel(IntPtr hToken)
    {
        int TOKEN_INFO_LENGTH = Marshal.SizeOf(typeof(int));
        IntPtr TOKEN_INFO_POINTER = Marshal.AllocHGlobal(TOKEN_INFO_LENGTH);

        try
        {
            if (!AdvApi32.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevationType, TOKEN_INFO_POINTER, TOKEN_INFO_LENGTH, out TOKEN_INFO_LENGTH))
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());

            return (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(TOKEN_INFO_POINTER);
        }
        catch
        {
            throw;
        }
        finally
        {
            if (TOKEN_INFO_POINTER != IntPtr.Zero)
                Marshal.FreeHGlobal(TOKEN_INFO_POINTER);
        }
    }

 public static IntPtr GetLinkedTokeIfRequiered(IntPtr hToken)
    {
        var TOKEN_ELEVATION = GetTokenElevationLevel(hToken);

        if (TOKEN_ELEVATION != TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
            return hToken;

        int TOKEN_INFO_LENGHT = Marshal.SizeOf(typeof(IntPtr));
        IntPtr LINKED_TOKEN_INFO = Marshal.AllocHGlobal(TOKEN_INFO_LENGHT);

        try
        {
            if (!AdvApi32.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenLinkedToken, LINKED_TOKEN_INFO, TOKEN_INFO_LENGHT, out TOKEN_INFO_LENGHT))
                throw new Win32Exception();

            return Marshal.ReadIntPtr(LINKED_TOKEN_INFO);
        }
        finally
        {
            if (LINKED_TOKEN_INFO != IntPtr.Zero)
                Marshal.Release(LINKED_TOKEN_INFO);
        }
    }
EN

回答 2

Stack Overflow用户

发布于 2018-06-07 14:37:31

谢谢你张贴其余的代码。我看你正在启动这一进程。我把这个添加到我的测试服务中,它仍然正确工作。

但我认为问题可能是GetLinkedTokeIfRequiered()中的这一行

代码语言:javascript
复制
Marshal.Release(LINKED_TOKEN_INFO);

这显然应该是:

代码语言:javascript
复制
Marshal.FreeHGlobal(LINKED_TOKEN_INFO);

解决这个问题,也许会奏效的。事情是这样,我很惊讶它没有崩溃。

这对我来说不是件容易的事。C#并不是我的强项。

为了使OP受益,用C++编写的测试服务的完整源代码可以:

代码语言:javascript
复制
#include <windows.h>
#include <wtsapi32.h>
#include <userenv.h>
#include <tchar.h>
#include <stdio.h>

#pragma comment (lib, "user32.lib")
#pragma comment (lib, "wtsapi32.lib")
#pragma comment (lib, "userenv.lib")
#pragma comment (lib, "advapi32.lib")

DWORD report_error (const char *operation)
{
    DWORD err = GetLastError ();
    return err;
}

// Launch notepad as currently logged-on user
DWORD LaunchProcess (DWORD SessionId, const char **failed_operation)
{
    HANDLE hToken;
    BOOL ok = WTSQueryUserToken (SessionId, &hToken);
    if (!ok)
        return report_error (*failed_operation = "WTSQueryUserToken");

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

    if (!ok)
    {
        CloseHandle (hToken);
        return report_error (*failed_operation = "CreateEnvironmentBlock");
    }

    TOKEN_LINKED_TOKEN lto;
    DWORD nbytes;
    ok = GetTokenInformation (hToken, TokenLinkedToken, &lto, sizeof (lto), &nbytes);

    if (ok)
    {
        CloseHandle (hToken);
        hToken = lto.LinkedToken;
    }

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

    // Do NOT want to inherit handles here, surely
    DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | /* CREATE_NEW_CONSOLE | */ CREATE_UNICODE_ENVIRONMENT;
    ok = CreateProcessAsUser (hToken, "c:\\windows\\system32\\notepad.exe", NULL, NULL, NULL, FALSE,
        dwCreationFlags, environment, NULL, &si, &pi);

    DestroyEnvironmentBlock (environment);
    CloseHandle (hToken);

    if (!ok)
        return report_error (*failed_operation = "CreateProcessAsUser");

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

// Determine the session ID of the currently logged-on user
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;
}


#define SERVICE_NAME __T ("demo_service")

bool quit;

// CtrlHandler callback
DWORD WINAPI CtrlHandler (DWORD dwControl, DWORD  dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
    if (dwControl == SERVICE_CONTROL_STOP)
        quit = true;
    return NO_ERROR;
}

// SvcMain callback
VOID WINAPI SvcMain (DWORD dwArgc, LPTSTR *lpszArgv)
{
    // Register for callbacks
    SERVICE_STATUS_HANDLE sh = RegisterServiceCtrlHandlerEx (SERVICE_NAME, CtrlHandler, NULL);

    // Tell the SCM that we are up and running
    SERVICE_STATUS ss = { };
    ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    ss.dwCurrentState = SERVICE_RUNNING;
    ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    SetServiceStatus (sh, &ss);

    TCHAR buf [256];
    const TCHAR *title = __T ("(c) 2018 Contoso Corporation");

    while (!quit)
    {
        DWORD response = IDOK;

        DWORD SessionId = GetCurrentSessionId ();
        if (SessionId == 0)
        {
            Sleep (2000);
            continue;
        }

        // Pop-up a message on the screen of the currently logged-on user (session 1)
        _stprintf (buf, __T ("Ready to launch..., SessionId = %d"), SessionId);
        WTSSendMessage (WTS_CURRENT_SERVER_HANDLE, SessionId, (TCHAR *) title, _tcslen (title),
            buf, _tcslen (buf), MB_OKCANCEL, 0, &response, TRUE);
        if (response == IDCANCEL)
            break;

        const char *failed_operation = "";
        DWORD dwResult = LaunchProcess (SessionId, &failed_operation);

        // Report results
        _stprintf (buf, __T ("LaunchProcess returned %lx from %s"), dwResult, failed_operation);
        WTSSendMessage (WTS_CURRENT_SERVER_HANDLE, SessionId, (char *) title, _tcslen (title),
            buf, _tcslen (buf), MB_OK, 0, &response, TRUE);

        FILE *logfile = fopen ("g:\\temp\\service.log", "at");
        if (logfile)
        {
            fprintf (logfile, "%s\n", buf);
            fclose (logfile);
        }
    }

    // Tell the SCM we are going away and exit
    ss.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus (sh, &ss);
}


// main
int main (void)
{
    SERVICE_TABLE_ENTRY DispatchTable [] = 
    { 
        { SERVICE_NAME, SvcMain }, 
        { NULL, NULL } 
    }; 

    // This call returns when the service has stopped. 
    // The process should simply terminate when the call returns.
    StartServiceCtrlDispatcher (DispatchTable);
    return 0;
}
票数 2
EN

Stack Overflow用户

发布于 2018-06-11 19:54:43

错误是STATUS_DLL_INIT_FAILED,这意味着缺少一个动态加载的DLL。也许您指定了错误的工作目录,而对LoadLibrary("lib_with_no_path.dll")的某些调用失败了?

如果在Event Viewer中查找,您应该能够看到缺少哪个DLL。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50644181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档