Exemplo n.º 1
0
        /// <summary>
        /// Uses P/Invoke to start the process using the login token obtained for the user.
        /// </summary>
        /// <param name="token">The login token to use to create the process with.</param>
        private void StartWithCreateProcessAsUser(IntPtr token)
        {
            var  startinfo      = _process.StartInfo;
            var  path           = Path.GetFullPath(startinfo.FileName);
            var  dir            = Path.GetDirectoryName(path);
            bool processCreated = false;

            Win32NativeMethods.PROCESS_INFORMATION pi        = new Win32NativeMethods.PROCESS_INFORMATION();
            Win32NativeMethods.SECURITY_ATTRIBUTES saProcess = new Win32NativeMethods.SECURITY_ATTRIBUTES();
            saProcess.bInheritHandle = true;
            saProcess.nLength        = (uint)Marshal.SizeOf(saProcess);

            Win32NativeMethods.SECURITY_ATTRIBUTES saThread = new Win32NativeMethods.SECURITY_ATTRIBUTES();
            saThread.bInheritHandle = true;
            saThread.nLength        = (uint)Marshal.SizeOf(saThread);

            Win32NativeMethods.STARTUPINFO si = new Win32NativeMethods.STARTUPINFO();
            si.lpDesktop = string.Empty;
            si.cb        = (uint)Marshal.SizeOf(si);

            lock (createProcessLock)
            {
                _pipeServerToClient        = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
                _pipeServerFromClient      = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
                _pipeServerErrorFromClient = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);

                try
                {
                    // although these are separate if statements, in reality all standard streams must be
                    // redirected otherwise it just won't work in SACS.
                    if (startinfo.RedirectStandardInput)
                    {
                        _standardInput           = new StreamWriter(_pipeServerToClient);
                        _standardInput.AutoFlush = true;
                    }

                    if (startinfo.RedirectStandardOutput)
                    {
                        Encoding encoding = (startinfo.StandardOutputEncoding != null) ? startinfo.StandardOutputEncoding : Console.OutputEncoding;
                        _standardOutput = new StreamReader(_pipeServerFromClient);
                    }

                    if (startinfo.RedirectStandardError)
                    {
                        Encoding encoding2 = (startinfo.StandardErrorEncoding != null) ? startinfo.StandardErrorEncoding : Console.OutputEncoding;
                        _standardError = new StreamReader(_pipeServerErrorFromClient);
                    }

                    ArgumentObject["pipeIn"]  = _pipeServerToClient.GetClientHandleAsString();
                    ArgumentObject["pipeOut"] = _pipeServerFromClient.GetClientHandleAsString();
                    ArgumentObject["pipeErr"] = _pipeServerErrorFromClient.GetClientHandleAsString();

                    processCreated = Win32NativeMethods.CreateProcessAsUser(
                        token,
                        path,
                        string.Format("\"{0}\" {1}", startinfo.FileName.Replace("\"", "\"\""), JsonConvert.SerializeObject(this.ArgumentObject)),
                        ref saProcess,
                        ref saThread,
                        true,
                        0,
                        IntPtr.Zero,
                        dir,
                        ref si,
                        out pi);

                    if (!processCreated)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    // For the last step, since we're not using the in-build methods to start the process,
                    // we need to replace the now outdated process
                    _process = Process.GetProcessById((int)pi.dwProcessId);
                }
                finally
                {
                    _pipeServerToClient.DisposeLocalCopyOfClientHandle();
                    _pipeServerFromClient.DisposeLocalCopyOfClientHandle();
                    _pipeServerErrorFromClient.DisposeLocalCopyOfClientHandle();

                    if (pi.hProcess != IntPtr.Zero)
                    {
                        Win32NativeMethods.CloseHandle(pi.hProcess);
                    }

                    if (pi.hThread != IntPtr.Zero)
                    {
                        Win32NativeMethods.CloseHandle(pi.hThread);
                    }
                }
            }
        }