public async Task Start(Connection connection, ElevationRequest request) { if (Settings.SecurityEnforceUacIsolation) { throw new NotSupportedException("VT Mode not supported when SecurityEnforceUacIsolation=true"); } int? exitCode; Task t1 = null, t2 = null, t3 = null; _connection = connection; System.Diagnostics.Process runningProcess = null; try { string command = request.FileName + " " + request.Arguments; using (var inputPipe = new PseudoConsolePipe()) using (var outputPipe = new PseudoConsolePipe()) { using (var pseudoConsole = PseudoConsole.PseudoConsole.Create(inputPipe.ReadSide, outputPipe.WriteSide, (short)request.ConsoleWidth, (short)request.ConsoleHeight)) { using (var process = StartPseudoConsole(command, PseudoConsole.PseudoConsole.PseudoConsoleThreadAttribute, pseudoConsole.Handle, request.StartFolder)) { runningProcess = System.Diagnostics.Process.GetProcessById(process.ProcessInfo.dwProcessId); // copy all pseudoconsole output to stdout t1 = Task.Run(() => CopyPipeToOutput(outputPipe.ReadSide)); // prompt for stdin input and send the result to the pseudoconsole t2 = Task.Run(() => CopyInputToPipe(inputPipe.WriteSide)); // discard Control stream t3 = new StreamReader(_connection.ControlStream, Settings.Encoding).ConsumeOutput((s) => Task.CompletedTask); Logger.Instance.Log($"Process ({process.ProcessInfo.dwProcessId}) started: {request.FileName} {request.Arguments}", LogLevel.Debug); // free resources in case the console is ungracefully closed (e.g. by the 'x' in the window titlebar) // var t3 = new StreamReader(pipe, Globals.Encoding).ConsumeOutput((s) => WriteToStdInput(s, process)); OnClose(() => DisposeResources(process, pseudoConsole, outputPipe, inputPipe)); WaitHandle.WaitAny(new WaitHandle[] { runningProcess.GetProcessWaitHandle(), connection.DisconnectedWaitHandle }); exitCode = process.GetExitCode(); } } } if (connection.IsAlive) { await connection.ControlStream.WriteAsync($"{Constants.TOKEN_EXITCODE}{exitCode ?? 0}{Constants.TOKEN_EXITCODE}").ConfigureAwait(false); } await connection.FlushAndCloseAll().ConfigureAwait(false); } catch (Exception ex) { Logger.Instance.Log(ex.ToString(), LogLevel.Error); await connection.ControlStream.WriteAsync($"{Constants.TOKEN_ERROR}Server Error: {ex.ToString()}\r\n{Constants.TOKEN_ERROR}").ConfigureAwait(false); await connection.FlushAndCloseAll().ConfigureAwait(false); return; } finally { if (runningProcess != null && !runningProcess.HasExited) { runningProcess.Terminate(); } } }