Console application doesn't periodically flush output
I'm using a 3rd party console application that periodically outputs data to the console line by line. When I attempted to run it through my App so that I can parse the output data, I noticed that the OutPutstream was readable only AFTER the application quits.
I tested my application with a C# console application that outputs som开发者_如何学Pythonething to the console every 5 seconds and it's working as expected. The 3rd party process I'm calling is either written in Java or C++ (not sure), but it seems that it might not adhere to the standards that .NET expects of console applications.
Is there another way to read the data output by a console application?
Edit: I'm calling the process from a WPF application. So async reads are required.
Edit 2: The console application reads data from a USB device (an accelerometer - http://www.gcdataconcepts.com/).
Below is the code I used:
public void RunProcess()
{
Process process = new Process();
process.StartInfo.FileName = "consoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
}
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!string.IsNullOrEmpty(outLine.Data))
{
Dispatcher.Invoke(new Action(() =>
{
textBlock1.Text += outLine.Data + Environment.NewLine;
}), System.Windows.Threading.DispatcherPriority.Normal);
}
}
protected virtual void StartProcess() {
// Start a new process for the cmd
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = FileName;
process.StartInfo.Arguments = Arguments;
process.StartInfo.WorkingDirectory = WorkingDirectory;
process.Start();
// Invoke stdOut and stdErr readers - each
// has its own thread to guarantee that they aren't
// blocked by, or cause a block to, the actual
// process running (or the gui).
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
new MethodInvoker(ReadStdErr).BeginInvoke(null, null);
}
/// <summary>
/// Handles reading of stdout and firing an event for
/// every line read
/// </summary>
protected virtual void ReadStdOut() {
string str;
while ((str = process.StandardOutput.ReadLine()) != null)
{
FireAsync(StdOutReceived, this, new DataReceivedEventArgs(str));
}
}
/// <summary>
/// Handles reading of stdErr
/// </summary>
protected virtual void ReadStdErr() {
string str;
while ((str = process.StandardError.ReadLine()) != null)
{
FireAsync(StdErrReceived, this, new DataReceivedEventArgs(str));
}
}
You can also do it like this:
public void RunProcess()
{
Process process = new Process();
process.StartInfo.FileName = "consoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
for (; ; )
{
string line = process.StandardOutput.ReadLine();
if (line == null)
break;
Dispatcher.Invoke(new Action(() =>
{
textBlock1.Text += outLine.Data + Environment.NewLine;
}), System.Windows.Threading.DispatcherPriority.Normal);
}
...
}
A simpler way would be to use StandardOutput
object on your process
object. Example code:
Process process = new Process();
process.StartInfo.FileName = @"StackOverflowTest.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
while (!process.StandardOutput.EndOfStream)
{
Console.WriteLine("got: " + process.StandardOutput.ReadLine());
}
精彩评论