如何将进程输出(控制台)重定向到richtextbox?
有什么问题,为什么richtextbox没有获得Process输出流? 在richtextbox中没有文本显示..
private void button1_Click(object sender, EventArgs e) { Process sortProcess; sortProcess = new Process(); sortProcess.StartInfo.FileName = "sort.exe"; sortProcess.StartInfo.Arguments = this.comboBox1.SelectedItem.ToString(); // Set UseShellExecute to false for redirection. sortProcess.StartInfo.CreateNoWindow = true; sortProcess.StartInfo.UseShellExecute = false; // Redirect the standard output of the sort command. // This stream is read asynchronously using an event handler. sortProcess.StartInfo.RedirectStandardOutput = true; sortOutput = new StringBuilder(""); // Set our event handler to asynchronously read the sort output. sortProcess.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler); // Redirect standard input as well. This stream // is used synchronously. sortProcess.StartInfo.RedirectStandardInput = true; // Start the process. sortProcess.Start(); // Start the asynchronous read of the sort output stream. sortProcess.BeginOutputReadLine(); sortProcess.WaitForExit(); richTextBox1.AppendText(sortOutput.ToString()); } private static void SortOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) { sortOutput.Append(Environment.NewLine + "[" + numOutputLines.ToString() + "] - " + outLine.Data); } }
所以当sort.exe启动时,它显示文本,我希望所有这些文本也显示在RealTime的richtextbox中(我不想等待进程退出,然后读取所有输出)
我该怎么做? 我的代码中有任何错误的部分? 谢谢
更新@botz
我在我的代码中添加了这个
private void SortOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) { sortOutput.Append(Environment.NewLine + "[" + numOutputLines.ToString() + "] - " + outLine.Data); richTextBox1.AppendText(sortOutput.ToString()); }
但它抛出了这个例外
Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.
WaitForExit()会阻止您的UI线程,因此您看不到新的输出。 要么在单独的线程中等待进程,要么用这样的东西替换WaitForExit()
:
while (!sortProcess.HasExited) { Application.DoEvents(); // This keeps your form responsive by processing events }
在SortOutputHandler
,您现在可以直接将输出附加到文本框中。 但是你应该记得检查是否需要在UI线程上调用它。
您可以在处理程序中以这种方式检查它是否在UI线程中:
if (richTextBox1.InvokeRequired) { richTextBox1.BeginInvoke(new DataReceivedEventHandler(SortOutputHandler), new[] { sendingProcess, outLine }); } else { sortOutput.Append(Environment.NewLine + "[" + numOutputLines.ToString() + "] - " + outLine.Data); richTextBox1.AppendText(sortOutput.ToString()); }
这对我有用:
private void button1_Click(object sender, EventArgs e) { using (Process sortProcess = new Process()) { sortProcess.StartInfo.FileName = @"F:\echo_hello.bat"; sortProcess.StartInfo.CreateNoWindow = true; sortProcess.StartInfo.UseShellExecute = false; sortProcess.StartInfo.RedirectStandardOutput = true; // Set event handler sortProcess.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler); // Start the process. sortProcess.Start(); // Start the asynchronous read sortProcess.BeginOutputReadLine(); sortProcess.WaitForExit(); } } void SortOutputHandler(object sender, DataReceivedEventArgs e) { Trace.WriteLine(e.Data); this.BeginInvoke(new MethodInvoker(() => { richTextBox1.AppendText(e.Data ?? string.Empty); })); }
您开始使用的示例是一个控制台应用程序,它不关心multithreading访问。 对于Windows窗体,当您更新控件时,必须从主UI线程完成,这就是需要BeginInvoke
原因。 如果要快速检查SortOutputHandler
类的处理程序是否正常工作,可以使用System.Diagnostics.Trace.Write*
,它不需要BeginInvoke
。
编辑: echo_hello.bat
简单地回应“你好”字符串:
@echo off echo hello
如果要从另一个线程更新ui,则需要确保您在主ui线程上。 在方法中检查InvokeRequired。 请参见InvokeRequired
完整的应用程序和源代码可从codeproject的外部链接获得:
http://www.codeproject.com/Articles/335909/Embedding-a-Console-in-aC-Application
这是https://github.com/dwmkerr/consolecontrol的实现教程。