C# 从windows服务获取要作为不同用户运行的应用程序

C# 从windows服务获取要作为不同用户运行的应用程序,c#,windows-services,impersonation,advapi32,C#,Windows Services,Impersonation,Advapi32,我做了很多研究,不知道为什么这不起作用,可能遗漏了一些简单的东西。代码确实会启动程序,但它会以本地系统用户而不是预期用户的身份启动程序 执行代码的服务的一部分: APIProcess.PROCESS_INFORMATION PI = new APIProcess.PROCESS_INFORMATION(); if (!APIProcess.Launch(@"C:\Windows\System32\notepad.exe", ".", "admin", "test"

我做了很多研究,不知道为什么这不起作用,可能遗漏了一些简单的东西。代码确实会启动程序,但它会以本地系统用户而不是预期用户的身份启动程序

执行代码的服务的一部分:

APIProcess.PROCESS_INFORMATION PI = new APIProcess.PROCESS_INFORMATION();
if (!APIProcess.Launch(@"C:\Windows\System32\notepad.exe", ".",
                "admin", "test", out string MSG, out PI))
            {
                logger.Debug(MSG);
            }
            else
            {
                logger.Debug(MSG);
                logger.Debug(PI.dwProcessID);
            }
具有隐藏功能的代码的一部分:

public static bool Launch(string appCmdLine, string Domain, string Username, string Password,out string MSG, out PROCESS_INFORMATION pi)
    {
        MSG = "";
        pi = new PROCESS_INFORMATION();
        bool ret = false;

        IntPtr Token = IntPtr.Zero;

        if (LogonUserA(Username,Domain,Password,LogonType.LOGON_NEW_CREDENTIALS,LogonProvider.PROVIDER_WINNT50,ref Token))
        {
            if (Token != IntPtr.Zero)
            {
                IntPtr envBlock = GetEnvironmentBlock(Token);
                ret = LaunchProcessAsUser(appCmdLine, Token, envBlock, out MSG, out pi);
                MSG = string.Join(", ",Token.ToString(),envBlock.ToString());
                if (envBlock != IntPtr.Zero)
                    DestroyEnvironmentBlock(envBlock);


                CloseHandle(Token);
            }

        }
        else
        {
            MSG = "Failed To Logon User";
        }
        return ret;
    }

[DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUserA(
        string Username,
        string Domain,
        string Password,
        LogonType LogonType,
        LogonProvider LogonProvider,
        ref IntPtr Token);

private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, out string Error, out PROCESS_INFORMATION pi)
    {
        bool result = false;
        Error = "";

        pi = new PROCESS_INFORMATION();
        SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
        SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
        saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
        saThread.nLength = (uint)Marshal.SizeOf(saThread);

        STARTUPINFO si = new STARTUPINFO();
        si.cb = (uint)Marshal.SizeOf(si);


        si.lpDesktop = @"WinSta0\Default"; //Modify as needed 
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
        si.wShowWindow = SW_SHOW;


        result = CreateProcessAsUser(
            token,
            null,
            cmdLine,
            ref saProcess,
            ref saThread,
            false,
            CREATE_UNICODE_ENVIRONMENT,
            envBlock,
            null,
            ref si,
            out pi);


        if (result == false)
        {
            int error = Marshal.GetLastWin32Error();
            string message = String.Format("CreateProcessAsUser Error: {0}", error);
            Error = message;
            //Debug.WriteLine(message);

        }

        return result;
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool CreateProcessAsUser(
       IntPtr hToken,
       string lpApplicationName,
       string lpCommandLine,
       ref SECURITY_ATTRIBUTES lpProcessAttributes,
       ref SECURITY_ATTRIBUTES lpThreadAttributes,
       bool bInheritHandles,
       uint dwCreationFlags,
       IntPtr lpEnvironment,
       string lpCurrentDirectory,
       ref STARTUPINFO lpStartupInfo,
       out PROCESS_INFORMATION lpProcessInformation);

我有一些日志记录,看起来用户令牌和环境令牌创建得很好。它也会启动预期的应用程序,但它会作为系统用户而不是预期的模拟用户启动。我可以让它工作,如果已经有一个程序在该用户下运行。例如,我更改了要启动的所需程序以及域/用户名/密码。

问题在于在对LogonUser的调用中使用了LOGON\u NEW\u凭据类型。发件人:

此登录类型允许调用方克隆其当前令牌并为出站连接指定新凭据新登录会话具有相同的本地标识符,但对其他网络连接使用不同的凭据


尝试改用LOGON32\u LOGON\u批处理。

您是否尝试过将服务配置为以所需用户的身份运行?您可以在services.msc中正确执行此操作。右键单击该服务,选择属性,登录选项卡。是的,问题是我需要该服务作为localsystem用户运行,因为它需要执行某些功能。它与登录的每个会话的客户端应用程序进行通信。这非常有效。我错过了一些简单的事情。谢谢