private static void RunTerminal() { if (!CreatePipe(out SafeFileHandle inputReadSide, out SafeFileHandle inputWriteSide, IntPtr.Zero, 0)) { throw new InvalidOperationException("failed to create input pipe"); } if (!CreatePipe(out SafeFileHandle outputReadSide, out SafeFileHandle outputWriteSide, IntPtr.Zero, 0)) { throw new InvalidOperationException("failed to create output pipe"); } // set up a background task to copy all pseudo console output to stdout Task.Run(() => Terminal.CopyPipeToOutput(outputReadSide)); IntPtr hPC = PseudoConsole.CreatePseudoConsole(inputReadSide, outputWriteSide); var process = Process.Start(hPC, "cmd.exe", (IntPtr)PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE); // prompt for stdin input and send the result to the pipe. // blocks until the user types "exit" Terminal.CopyInputToPipe(inputWriteSide); Process.CleanUp(process); ClosePseudoConsole(hPC); inputReadSide.Dispose(); inputWriteSide.Dispose(); outputReadSide.Dispose(); outputWriteSide.Dispose(); }
public Terminal(string command, int windowWidth, int windowHeight) { inputPipe = new PseudoConsolePipe(); outputPipe = new PseudoConsolePipe(); pseudoConsole = PseudoConsole.Create(inputPipe.ReadSide, outputPipe.WriteSide, windowWidth, windowHeight); process = ProcessFactory.Start(command, PseudoConsole.PseudoConsoleThreadAttribute, pseudoConsole.Handle); writer = new FileStream(inputPipe.WriteSide, FileAccess.Write); reader = new FileStream(outputPipe.ReadSide, FileAccess.Read); }
/// <summary> /// Start the pseudoconsole and run the process as shown in /// https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#creating-the-pseudoconsole /// </summary> /// <param name="command">the command to run, e.g. cmd.exe</param> public void Run(string command) { using (var inputPipe = new PseudoConsolePipe()) using (var outputPipe = new PseudoConsolePipe()) using (var pseudoConsole = PseudoConsole.Create(inputPipe.ReadSide, outputPipe.WriteSide, (short)Console.WindowWidth, (short)Console.WindowHeight)) using (var process = ProcessFactory.Start(command, PseudoConsole.PseudoConsoleThreadAttribute, pseudoConsole.Handle)) { // copy all pseudoconsole output to stdout Task.Run(() => CopyPipeToOutput(outputPipe.ReadSide)); // prompt for stdin input and send the result to the pseudoconsole Task.Run(() => CopyInputToPipe(inputPipe.WriteSide)); // free resources in case the console is ungracefully closed (e.g. by the 'x' in the window titlebar) OnClose(() => DisposeResources(process, pseudoConsole, outputPipe, inputPipe)); WaitForExit(process).WaitOne(Timeout.Infinite); } }