Redirect input and output for cmd.exe
c#, cmd, console, stdin, stdout
Solution
To achieve such behavior you should use `/k` switch to run `cmd.exe` in interactive mode.
The problem is to separate inputs from different commands. To do this you could change the standard prompt using `prompt` command:
prompt --Prompt_C2BCE8F8E2C24403A71CA4B7F7521F5B_F659E9F3F8574A72BE92206596C423D5
So now it is pretty easy to determine the end of command output.
Here is the complete code:
public static IEnumerable<string> RunCommands(params string[] commands) {
var process = new Process {
StartInfo = new ProcessStartInfo("cmd") {
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
Arguments = "/k",
}
};
process.Start();
const string prompt = "--Prompt_C2BCE8F8E2C24403A71CA4B7F7521F5B_F659E9F3F8574A72BE92206596C423D5 ";
// replacing standard prompt in order to determine end of command output
process.StandardInput.WriteLine("prompt " + prompt);
process.StandardInput.Flush();
process.StandardOutput.ReadLine();
process.StandardOutput.ReadLine();
var result = new List<string>();
try {
var commandResult = new StringBuilder();
foreach (var command in commands) {
process.StandardInput.WriteLine(command);
process.StandardInput.WriteLine();
process.StandardInput.Flush();
process.StandardOutput.ReadLine();
while (true) {
var line = process.StandardOutput.ReadLine();
if (line == prompt) // end of command output
break;
commandResult.AppendLine(line);
}
result.Add(commandResult.ToString());
commandResult.Clear();
}
} finally {
process.Kill();
}
return result;
}
It works well but it looks like one big hack.
I'd recommend you to use process per command instead.
Problem
I wanna redirect cmd.exe output somewhere, below code works when the command is a line: ``` Process p = new Process() { StartInfo = new ProcessStartInfo("cmd") { UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, CreateNoWindow = true, Arguments = String.Format("/c \"{0}\"", command), } }; p.OutputDataReceived += (s, e) => Messagebox.Show(e.Data); p.Start(); p.BeginOutputReadLine(); p.WaitForExit(); ``` But how about a series commands like WriteLine(): ``` p.StandardInput.WriteLine("cd..."); p.StandardInput.WriteLine("dir"); ``` how to get output in this situation?