I have a small wrapping application to give a GUI to an existing console application. I’m using the ProcessStartInfo and Process class to bind to the .exe, and then using BeginErrorReadLine() and BeginOutputReadLine() to redirect any messages into the new GUI. Everything works fine except for when the console calls Console.Write() instead Console.WriteLine(), in which case the text passed to Write is not displayed at all. I would think that the problem is because the WriteLine function inserts a line break after the text, and the Write method does not. Is there any way to circumvent this? I can’t change it from Write to WriteLine in the original command line program as Write is used to prompt for input.
Relevant Code:
var startInfo = new ProcessStartInfo(ServerFile);
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
ServerProc = new Process();
ServerProc.StartInfo = startInfo;
ServerProc.EnableRaisingEvents = true;
ServerProc.ErrorDataReceived += new DataReceivedEventHandler(ServerProc_ErrorDataReceived);
ServerProc.OutputDataReceived += new DataReceivedEventHandler(ServerProc_OutputDataReceived);
private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
ConsoleTextBlock.Text += e.Data + "\r\n";
ConsoleScroll.ScrollToEnd();
}));
}
private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Dispatcher.Invoke(new Action(() =>
{
ConsoleTextBlock.Text += e.Data + "\r\n";
ConsoleScroll.ScrollToEnd();
}));
}
The problem you are experiencing is that the
Processclass is set up for convenient line-oriented event-based processing of the output of the process. You cannot use this functionality if you need to read partial lines as they are being output.Nevertheless, the
Processclass does give you the tools you need if you need finer-grained control over the output than the line-oriented facilities. If you redirect the output, thenProcess.StandardOutputis aStreamReaderand you have the wholeStreamReaderAPI that you can use instead of being forced to read entire lines.For example, here is a character-by-character read of the standard output:
If we run it on another console program that produces this output:
It produces this output:
which shows that the
"abc"was read one second before the rest of the line.However, this is not convenient if you like the event-oriented I/O already provided by
Process. You can either:StreamAPIand perhaps even roll your own event-based I/O that meets your needs.
You are writing a program that is parsing another program’s character-oriented output and so without full lines you will need some sort of timeout to indicate “I now satisfied that the program is done producing output for the time being.” This can be easy or hard depending on how predictable the output is. For example, you might be able to recognize a prompt that ends with a
"?". It depends on your situation.The point is that you’ll have to use the
StandardOutputandStandardErrorStreamReaderproperties if you want something other than line-oriented I/O.