public static char[,] ReadConsoleRaw() { NativeInterface.CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo = ConsoleInterface.getScreenBufferInfo(); NativeInterface.SMALL_RECT readRegion = default(NativeInterface.SMALL_RECT); readRegion.Right = screenBufferInfo.dwSize.X; readRegion.Bottom = (short)(screenBufferInfo.dwCursorPosition.Y + 1); // read all lines from the top of the screen buffer to the current cursor position (inclusive) NativeInterface.CHAR_INFO[] charInfos = new NativeInterface.CHAR_INFO[screenBufferInfo.dwSize.X * screenBufferInfo.dwSize.Y]; using (SafeHandle hConsoleOutput = ConsoleInterface.getConsoleOutputHandle()) { ConsoleInterface.callWin32Func(() => NativeInterface.ReadConsoleOutput(hConsoleOutput, charInfos, screenBufferInfo.dwSize, default(NativeInterface.COORD), ref readRegion)); } char[,] output = new char[screenBufferInfo.dwSize.X, readRegion.Bottom]; for (int y = 0; y < readRegion.Bottom; y++) { for (int x = 0; x < screenBufferInfo.dwSize.X; x++) { output[x, y] = charInfos[y * screenBufferInfo.dwSize.X + x].UnicodeChar; } } return(output); }
public static void WriteConsole(string data) { using (SafeHandle hConsoleInput = ConsoleInterface.getConsoleInputHandle()) { // we need 2x the number of characters because we need to simulate key press and key release events for each character NativeInterface.INPUT_RECORD[] inputRecords = new NativeInterface.INPUT_RECORD[data.Length * 2]; for (int i = 0; i < data.Length; i++) { NativeInterface.KEY_EVENT_RECORD keyPressEvent = default(NativeInterface.KEY_EVENT_RECORD); keyPressEvent.bKeyDown = true; keyPressEvent.wRepeatCount = 1; keyPressEvent.UnicodeChar = data[i]; NativeInterface.KEY_EVENT_RECORD keyReleaseEvent = keyPressEvent; // same values for all fields as the key press event, but with the bKeyDown field as "false" keyReleaseEvent.bKeyDown = false; inputRecords[i * 2].EventType = NativeInterface.KEY_EVENT; inputRecords[i * 2].Event = keyPressEvent; inputRecords[i * 2 + 1].EventType = NativeInterface.KEY_EVENT; inputRecords[i * 2 + 1].Event = keyReleaseEvent; } int recordsWritten; ConsoleInterface.callWin32Func(() => NativeInterface.WriteConsoleInput(hConsoleInput, inputRecords, inputRecords.Length, out recordsWritten)); } }
private static NativeInterface.CONSOLE_SCREEN_BUFFER_INFO getScreenBufferInfo() { using (SafeHandle hConsoleOutput = ConsoleInterface.getConsoleOutputHandle()) { NativeInterface.CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo = default(NativeInterface.CONSOLE_SCREEN_BUFFER_INFO); ConsoleInterface.callWin32Func(() => NativeInterface.GetConsoleScreenBufferInfo(hConsoleOutput, out screenBufferInfo)); return(screenBufferInfo); } }
public static void ClearConsole() { using (SafeHandle hConsoleOutput = ConsoleInterface.getConsoleOutputHandle()) { // get dimensions of the screen buffer NativeInterface.CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo = ConsoleInterface.getScreenBufferInfo(); int charsToWrite = screenBufferInfo.dwSize.X * screenBufferInfo.dwSize.Y; int charsWritten; ConsoleInterface.callWin32Func(() => NativeInterface.FillConsoleOutputCharacter(hConsoleOutput, ConsoleInterface.SPACE_CHAR, charsToWrite, default(NativeInterface.COORD), out charsWritten)); ConsoleInterface.callWin32Func(() => NativeInterface.SetConsoleCursorPosition(hConsoleOutput, default(NativeInterface.COORD))); } }
public static void AttachToConsole(int processId, TimeSpan timeout) { ConsoleInterface.callWin32Func(() => NativeInterface.FreeConsole()); DateTime startTime = DateTime.Now; do { if (NativeInterface.AttachConsole(processId)) { return; } } while (startTime + timeout > DateTime.Now); throw new TimeoutException(); }
public static string ReadConsole() { char[,] output = ConsoleInterface.ReadConsoleRaw(); StringBuilder buffer = new StringBuilder(); for (int y = 0; y < output.GetLength(1); y++) { char[] lineChars = new char[output.GetLength(0)]; for (int i = 0; i < lineChars.Length; i++) { lineChars[i] = output[i, y]; } buffer.AppendLine(new String(lineChars).TrimEnd()); } return(buffer.ToString().TrimEnd()); }
public void Run() { this.commandPipe.Connect(); bool shouldContinue = true; try { while (shouldContinue) { int opcode = this.commandReader.ReadByte(); CommandResult result = CommandResult.GeneralFailure; bool shouldWriteResult = true; // individual opcodes can set this to false to return specialized data switch ((ProxyCommand)opcode) { case ProxyCommand.StartProcess: if (this.process == null) { this.process = new Process(); this.process.StartInfo.FileName = this.commandReader.ReadString(); this.process.StartInfo.Arguments = this.commandReader.ReadString(); this.process.StartInfo.WorkingDirectory = this.commandReader.ReadString(); this.process.StartInfo.UseShellExecute = false; this.process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; try { this.process.Start(); this.spawnedProcess = true; result = CommandResult.Success; } catch (Exception) { result = CommandResult.CouldNotSpawnChild; this.process.Dispose(); this.process = null; } } else { result = CommandResult.ChildAlreadySpawned; } break; case ProxyCommand.SetPid: if (this.process == null) { try { int pid = this.commandReader.ReadInt32(); this.process = Process.GetProcessById(pid); result = CommandResult.Success; } catch (Exception) { result = CommandResult.ProcessDoesNotExist; } } break; case ProxyCommand.KillProcess: if (this.process != null) { this.process.Kill(); this.process.WaitForExit(); this.commandWriter.Write((byte)CommandResult.Success); this.commandWriter.Write(this.process.ExitCode); this.process.Dispose(); this.process = null; shouldWriteResult = false; shouldContinue = false; } else { result = CommandResult.ChildNotSpawned; } break; case ProxyCommand.AttachConsole: int timeoutMs = this.commandReader.ReadInt32(); if (this.process != null) { ConsoleInterface.AttachToConsole(this.process.Id, TimeSpan.FromMilliseconds(timeoutMs)); result = CommandResult.Success; } else { result = CommandResult.ChildNotSpawned; } break; case ProxyCommand.ReadConsole: string outputData = ConsoleInterface.ReadConsole(); shouldWriteResult = false; this.commandWriter.Write((byte)CommandResult.Success); this.commandWriter.Write(outputData); break; case ProxyCommand.WriteConsole: string inputData = this.commandReader.ReadString(); ConsoleInterface.WriteConsole(inputData); result = CommandResult.Success; break; case ProxyCommand.ClearConsole: ConsoleInterface.ClearConsole(); result = CommandResult.Success; break; case ProxyCommand.GetHasProcessExited: if (this.process != null) { this.commandWriter.Write((byte)CommandResult.Success); this.commandWriter.Write(this.process.HasExited); shouldWriteResult = false; } else { result = CommandResult.ChildNotSpawned; } break; case ProxyCommand.GetPid: if (this.process != null) { this.commandWriter.Write((byte)CommandResult.Success); this.commandWriter.Write(this.process.Id); shouldWriteResult = false; } else { result = CommandResult.ChildNotSpawned; } break; case ProxyCommand.GetProcessExitCode: if (this.process != null) { if (this.process.HasExited) { this.commandWriter.Write((byte)CommandResult.Success); this.commandWriter.Write(this.process.ExitCode); shouldWriteResult = false; } else { result = CommandResult.ChildHasNotExited; } } else { result = CommandResult.ChildNotSpawned; } break; default: result = CommandResult.GeneralFailure; break; } if (shouldWriteResult) { this.commandWriter.Write((byte)result); } this.commandWriter.Flush(); } } finally // ensure that the child process is killed if we exit, but only if we spawned the process { if (this.process != null && this.spawnedProcess) { this.process.Kill(); } } }
private static SafeHandle getConsoleOutputHandle() { return(ConsoleInterface.getConsoleHandle(NativeInterface.STD_OUTPUT_HANDLE)); }