Частично прочитать стандартный вывод другого процесса, созданного из приложения С#.
Вопрос
У меня есть приложение с графическим интерфейсом, в котором я создаю консольное приложение, используя класс Process.
Process p1 = new Process();
p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p1.StartInfo.CreateNoWindow = true;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe");
p1.StartInfo.Arguments = "/pn abc.exe /f \"temp1.txt\"";
p1.StartInfo.RedirectStandardError = true;
p1.StartInfo.RedirectStandardInput = true;
p1.StartInfo.RedirectStandardOutput = true;
p1.OutputDataReceived += new DataReceivedEventHandler(outputreceived);
p1.ErrorDataReceived += new DataReceivedEventHandler(errorreceived);
p1.Start();
tocmd = p1.StandardInput;
p1.BeginOutputReadLine();
p1.BeginErrorReadLine();
Теперь у меня проблема: хотя он и считывает вывод консоли асинхронно, но, похоже, событие запускает только тогда, когда внутренний буфер заполнен некоторой суммой.Я хочу, чтобы он отображал данные по мере их поступления.Если в буфере 10 байт, пусть он отобразит 10 байт.Моя программа реализует внутренний вызов Sleep(), поэтому мне нужно печатать данные, пока она не перейдет в режим сна.
Как мне это сделать?
=============
Как уже упоминалось, вывод буферизуется по строкам, я попробовал следующее изменение в коде.
p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p1.StartInfo.CreateNoWindow = true;
p1.StartInfo.UseShellExecute = false;
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe");
p1.StartInfo.Arguments = pnswitch + " /f \"temp1.txt\"";
p1.StartInfo.RedirectStandardError = false;
p1.StartInfo.RedirectStandardInput = true;
p1.StartInfo.RedirectStandardOutput = true;
p1.Start();
tocmd = p1.StandardInput;
MethodInvoker mi = new MethodInvoker(readout);
mi.BeginInvoke(null, p1);
и внутри показания я написал
void readout()
{
string str;
while ((str = p1.StandardOutput.ReadLine()) != null)
{
richTextBox1.Invoke(new UpdateOutputCallback(this.updateoutput), new object[] { str });
p1.StandardOutput.BaseStream.Flush();
}
}
Я думаю, теперь он отслеживает, когда пишется каждая строка, и печатает ее, верно?это тоже не сработало.Там что-то не так?
Решение
Полученные выходные данные и данные об ошибках буферизуются по строкам и срабатывают только при добавлении новой строки.
Лучше всего использовать собственное устройство чтения, которое может читать входные данные побайтово.Очевидно, это должно быть неблокирующим :)
Другие советы
Для этого необходимо использовать синхронные операции чтения в перенаправленном потоке.Ваш код будет выглядеть следующим образом (пример MSDN):
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
**string output = p.StandardOutput.ReadToEnd();**
p.WaitForExit();
Чтобы добиться асинхронного поведения, вам придется использовать несколько потоков.
Статья MSDN здесь