Частично прочитать стандартный вывод другого процесса, созданного из приложения С#.

StackOverflow https://stackoverflow.com/questions/625856

Вопрос

У меня есть приложение с графическим интерфейсом, в котором я создаю консольное приложение, используя класс 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 здесь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top