views:

443

answers:

1

Hi Guys,

I am using VBOXMANAGE to "export" a guest machine. VBOXManage is a Console application that can control the guest machine's behavior from the host. Since the export command is a long process, it returns process updates like so:

0%...10%...20%...30%...100%

I am writing a C# application that will invoke VBOXManage using Process. Here's my code:

Process VBOXProc = new Process();

VBOXProc.StartInfo.FileName = VBOXMANAGE;
VBOXProc.StartInfo.Arguments = Arguments;
VBOXProc.StartInfo.UseShellExecute = false;
VBOXProc.StartInfo.CreateNoWindow = true;
VBOXProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
VBOXProc.StartInfo.RedirectStandardError = true;
VBOXProc.StartInfo.RedirectStandardOutput = true;

VBOXProc.OutputDataReceived += new DataReceivedEventHandler(VBOXProc_OutputDataReceived);
VBOXProc.ErrorDataReceived += new DataReceivedEventHandler(VBOXProc_ErrorDataReceived);

VBOXProc.EnableRaisingEvents = true;

VBOXProc.Start();
VBOXProc.BeginOutputReadLine();
VBOXProc.BeginErrorReadLine();

VBOXProc.WaitForExit();

This is fine, except that the output is being read per LINE. This means that the process updates " 0%...10%...20%...30%...100%" will only show AFTER the actual process is done.

Is there a way to capture the console output in realtime?

Thanks!

+1  A: 

You can read directly from the StanadardOutput/Error for the process using all the standard Stream methods, just be sure to set the StartInfo.Redirectxxx to true.

var p = new Process()
p.StartInfo.UseShellExecute = false;  //not sure if this is absolutely required
p.StartInfo.RedirectStandardOuput = true;
....

do
{
  Thread.Sleep(nnn);
  Console.Out.Write(p.StandardOutput.ReadToEnd());
}
while (!p.HasExited);
//catch any leftovers in redirected stdout
Console.Out.Write(p.StandardOutput.ReadToEnd());

The above will echo the output of the child process to your applications Standard Out.

You can read Blocks of a particular size using p.StandardOutput.Read(char[], int, int) or asynchronous reads using p.StadardOutput.BaseStream.BeginRead(...).

All the same methods are available for StandardError.

Sleeping in the loop frees up the processor for other tasks and allows some data to accumulate in the bufffer. If the sleep period is too long and the buffer overflows some output from the executing process will be lost. If the sleep period is too short a lot of CPU cycles are spent reading and empty buffer.

ScottS
Hi, the above code is somewhat unreliable... I am getting truncated texts.
Ian
Yes, depending on the timing of writes to stdout and process termination there may be some data left in the buffer after the loop terminates. Another read after the loop will pick up any missing data. I mainly wanted to point out that all the stream methods are available. In production code I would likely sleep or otherwise release the processor in the loop and only read "occaisionally".
ScottS