如何使用参数创建进程作为用户

时间:2018-02-28 09:21:51

标签: c# windows-services createprocessasuser system-services

尝试以portablechrome.exe作为用户创建进程,但我无法使用参数处理它。

如何打开带参数的HTML文件? 例如portablechrome.exe sample.html --kiosk

我正在使用这样的系统服务:

string url = @System.AppDomain.CurrentDomain.BaseDirectory + "updater.html ";
string kioskMode = url + " --kiosk --incognito --disable-pinch --overscroll-history-navigation=0 ";

StartProcessAsCurrentUser("C:\\Chrome\\PortableChrome.exe", kioskMode);

我的StartProcessAsUser包装器:

public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true)
{
    appPath = appPath + " " + cmdLine;
    var hUserToken = IntPtr.Zero;
    var startInfo = new STARTUPINFO();
    var procInfo = new PROCESS_INFORMATION();
    var pEnv = IntPtr.Zero;
    int iResultOfCreateProcessAsUser;

    startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));

    try
    {
        if (!GetSessionUserToken(ref hUserToken))
        {
            throw new Exception("StartProcessAsCurrentUser: GetSessionUserToken failed.");
        }

        uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
        startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
        startInfo.lpDesktop = "winsta0\\default";

        if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))
        {
            throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");
        }

        if (!CreateProcessAsUser(hUserToken,
            appPath, // Application Name
            cmdLine, // Command Line
            IntPtr.Zero,
            IntPtr.Zero,
            false,
            dwCreationFlags,
            pEnv,
            workDir, // Working directory
            ref startInfo,
            out procInfo))
        {
            iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
            throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed.  Error Code -" + iResultOfCreateProcessAsUser);
        }

在我调用此功能后,自助服务终端模式会启用Chrome,但不会打开我的html文件。只是一个空白页面。

那么如何打开带参数的html文件?

1 个答案:

答案 0 :(得分:0)

删除

appPath = appPath + " " + cmdLine;

并使用

替换CreateProcessAsUser cmlLine参数
$@"""{appPath}"" {cmdLine}"

我们遇到了同样的问题并且花了很多时间来弄明白

工作示例

    static void Main()
    {
        var url = @"Test.html";
        var kioskMode = url + " --kiosk --incognito --disable-pinch --overscroll-history-navigation=0 ";

        StartProcessAsCurrentUser(@"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", kioskMode);
    }

    public static bool StartProcessAsCurrentUser(string appPath, string cmdLine = null, string workDir = null, bool visible = true)
    {
        var hUserToken = IntPtr.Zero;
        var startInfo = new STARTUPINFO();
        var procInfo = new PROCESS_INFORMATION();
        var pEnv = IntPtr.Zero;

        startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));
        hUserToken = WindowsIdentity.GetCurrent().Token; //get current user token

        var dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint) (visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
        startInfo.wShowWindow = (short) (visible ? SW.SW_SHOW : SW.SW_HIDE);
        startInfo.lpDesktop = "winsta0\\default";

        if (!CreateEnvironmentBlock(out pEnv, hUserToken, 0))
        {
            throw new Exception("StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");
        }

        if (!CreateProcessAsUser(hUserToken,
            appPath, // Application Name
            $@"""{appPath}"" {cmdLine}", // Command Line
            IntPtr.Zero,
            IntPtr.Zero,
            false,
            dwCreationFlags,
            pEnv,
            workDir, // Working directory
            ref startInfo,
            out procInfo))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }

        return true;
    }

    private const int CREATE_NO_WINDOW = 0x08000000;
    private const int CREATE_NEW_CONSOLE = 0x00000010;
    private const int CREATE_UNICODE_ENVIRONMENT = 0x400;

    [DllImport("userenv.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, int bInherit);

    [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    public static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandle, uint dwCreationFlags,
        IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

    [StructLayout(LayoutKind.Sequential)]
    public struct STARTUPINFO
    {
        public int cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public uint dwProcessId;
        public uint dwThreadId;
    }

    public enum SW
    {
        SW_HIDE = 0,
        SW_SHOWNORMAL = 1,
        SW_NORMAL = 1,
        SW_SHOWMINIMIZED = 2,
        SW_SHOWMAXIMIZED = 3, // these two enum members actually have the same value
        SW_MAXIMIZE = 3, // assigned to them This is not an error
        SW_SHOWNOACTIVATE = 4,
        SW_SHOW = 5,
        SW_MINIMIZE = 6,
        SW_SHOWMINNOACTIVE = 7,
        SW_SHOWNA = 8,
        SW_RESTORE = 9,
        SW_SHOWDEFAULT = 10,
        SW_FORCEMINIMIZE = 11,
        SW_MAX = 12
    }