使用Process实时控制台输出重定向

Ian*_*Ian 13 c# process console-redirect

我正在使用VBOXMANAGE"导出"客户机.VBOXManage是一个控制台应用程序,可以控制来宾主机的来宾行为.由于export命令是一个很长的进程,它会返回进程更新,如下所示:

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

我正在编写一个C#应用程序,它将使用Process调用VBOXManage.这是我的代码:

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();
Run Code Online (Sandbox Code Playgroud)

这很好,除了每个LINE读取输出.这意味着过程更新"0%... 10%... 20%... 30%... 100%"仅在实际过程完成后显示.

有没有办法实时捕获控制台输出?

谢谢!

Sco*_*ttS 6

您可以使用所有标准Stream方法直接从StanadardOutput/Error读取进程,只需确保将StartInfo.Redirectxxx设置为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());
Run Code Online (Sandbox Code Playgroud)

以上内容将子进程的输出回显给您的应用程序标准输出.

您可以使用p.StandardOutput.Read(char [],int,int)读取特定大小的块或使用p.StadardOutput.BaseStream.BeginRead(...)读取异步读取.

所有相同的方法都可用于StandardError.

在循环中休眠会释放处理器以执行其他任务,并允许一些数据在缓冲区中累积.如果睡眠周期太长并且缓冲区溢出,则执行过程中的某些输出将丢失.如果睡眠时间太短,则会花费很多CPU周期来读取和清空缓冲区.


Ani*_*ish 6

这对我有用

        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.ErrorDialog = false;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.UseShellExecute = false;

        process.ErrorDataReceived += (sendingProcess, errorLine) => error.AppendLine(errorLine.Data);
        process.OutputDataReceived += (sendingProcess, dataLine) => SetMessage(dataLine.Data);

        process.Start();
        process.BeginErrorReadLine();
        process.BeginOutputReadLine();

        process.WaitForExit();
Run Code Online (Sandbox Code Playgroud)

error.AppendLine()和SetMessage()是我的方法.