有什么问题,为什么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.
答案 0 :(得分:5)
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());
}
答案 1 :(得分:3)
这对我有用:
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);
}));
}
The example you started with是一个控制台应用程序,它不关心多线程访问。对于Windows窗体,当您更新控件时,必须从主UI线程完成,这就是需要BeginInvoke
的原因。如果您想快速检查SortOutputHandler
之类的处理程序是否正常工作,您可以使用System.Diagnostics.Trace.Write*
,而不需要BeginInvoke
。
编辑: echo_hello.bat
简单地回应“你好”字符串:
@echo off
echo hello
答案 2 :(得分:0)
如果你要从另一个线程更新ui,你需要确保你在主ui线程上。在方法中检查InvokeRequired。见InvokeRequired
答案 3 :(得分:0)
可从codeproject的外部链接获得完整的应用程序和源代码:
http://www.codeproject.com/Articles/335909/Embedding-a-Console-in-a-C-Application
答案 4 :(得分:0)
正如我在发布给问题的评论中所说,根据定义排序的含义,在读取所有输入之前不可能有任何输出。因此,排序程序是实时获取输出的不良示例。因此,以下内容适用于将来希望对控制台程序进行一般操作的任何人。以下使用BackgroundWorker
异步获取输出并将其放入TextBox
中。可以轻松地使用RichTextBox
。
public partial class MainWindow : Window
{
const string Path = @"C:\Windows\system32\sort.exe";
BackgroundWorker Processer = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
Processer.WorkerReportsProgress = true;
Processer.WorkerSupportsCancellation = true;
Processer.ProgressChanged += Processer_ProgressChanged;
Processer.DoWork += Processer_DoWork;
}
private void Processer_DoWork(object sender, DoWorkEventArgs e)
{
StreamReader StandardOutput = e.Argument as StreamReader;
string data = StandardOutput.ReadLine();
while (data != null)
{
Processer.ReportProgress(0, data);
data = StandardOutput.ReadLine();
}
}
private void Processer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string data = e.UserState as string;
if (data != null)
DataBox.Text += data + "\r\n";
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
DataBox.Text = string.Empty;
ProcessStartInfo StartInfo = new ProcessStartInfo(Path);
StartInfo.RedirectStandardOutput = true;
StartInfo.RedirectStandardInput = true;
StartInfo.UseShellExecute = false;
Process p = null;
try { p = Process.Start(StartInfo); }
catch (Exception ex)
{
MessageBox.Show($"Error starting {Path}: {ex.Message}");
return;
}
// Get the output
Processer.RunWorkerAsync(p.StandardOutput);
// Put the input
p.StandardInput.WriteLine("John");
p.StandardInput.WriteLine("Alice");
p.StandardInput.WriteLine("Zoe");
p.StandardInput.WriteLine("Bob");
p.StandardInput.WriteLine("Mary");
// Tell the program that is the last of the data
p.StandardInput.Close();
}
}
对于排序程序,直到读取完所有数据之后才需要调用ReportProgress,但这是一个更通用的示例。