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

我正在使用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(); 

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

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

谢谢!

您可以使用所有标准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()); 

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

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

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

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

这对我有用

  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(); 

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

尝试重定向标准输入,并将AutoFlush应用于StandardInput。 接下来使用StreamReader读取流。

 Process proces; ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "test.exe"; psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.RedirectStandardOutput = true; psi.RedirectStandardInput = true; proces = Process.Start(psi); proces.StandardInput.AutoFlush = true; 

对不起任何错误,我是巴西人,并使用谷歌翻译来写这篇文章。

巧合的是,我也在做一个与Virtualbox的VBoxManage一起工作的程序。 在我的情况下,除其他外,我想要转换虚拟磁盘。 它也延迟了,也有进步的百分比

我设法通过创建运行程序的意愿流程,并使用用户类’Dean North`这个与此类似的另一个问题来做到这一点。 使用线程运行VBoxManage很重要,否则无法处理获取的文本或查看进度。

Otextoémuitogrande pra eu adicionarquatroespaçosantesde cada linha e repassar。

这些类取代了Process系统类。 不需要对代码进行任何更改,只需添加一个arquivo.cs,其中包含用户Dean North传递的文本而不是Process p = new Process()使用FixedProcess p = new FixedProcess ()

之后是我的代码:

 private void BotaoParaTestes_Click(object sender, EventArgs e) { string linha = @"clonehd " + "\"Z:\\Máquinas Virtuais\\Teste.vdi\" " + "\"C:\\Temp\\teste.vdi\" " + "--format VDI --variant Standard"; Thread tarefa = new Thread(Executar); tarefa.Start(linha); } private void Executar(object Linha) { FixedProcess fp = new FixedProcess (); fp.StartInfo.FileName = ItensEstaticos.VBox; fp.StartInfo.Arguments = Linha.ToString(); fp.StartInfo.CreateNoWindow = true; fp.StartInfo.ErrorDialog = false; fp.StartInfo.RedirectStandardError = true; fp.StartInfo.RedirectStandardOutput = true; fp.StartInfo.UseShellExecute = false; fp.ErrorDataReceived += (sendingProcess, errorLine) => Escrita(errorLine.Data); fp.OutputDataReceived += (sendingProcess, dataLine) => Escrita(dataLine.Data); fp.Start(); fp.BeginErrorReadLine(); fp.BeginOutputReadLine(); fp.WaitForExit(); } private void Escrita(string Texto) { if (!string.IsNullOrEmpty(Texto)) { BeginInvoke(new MethodInvoker(delegate { this.Texto.Text += Texto; })); } } 

对我来说,事件仅在文本更改时调用,而不仅仅是在VBoxManage转到新行时。 有时文本为null,然后在使用为控件获取的文本之前放置检查结构。