Обтекание процесса, некоторые выходные данные не отображаются - PullRequest
3 голосов
/ 03 июля 2011

У меня есть небольшое приложение-оболочка для предоставления графического интерфейса существующему консольному приложению. Я использую классы ProcessStartInfo и Process для привязки к .exe, а затем использую BeginErrorReadLine() и BeginOutputReadLine() для перенаправления любых сообщений в новый графический интерфейс. Все работает нормально, за исключением случаев, когда консоль вызывает Console.Write() вместо Console.WriteLine(), и в этом случае текст, переданный Write, вообще не отображается. Я думаю, что проблема в том, что функция WriteLine вставляет разрыв текста после текста, а метод Write - нет. Есть ли способ обойти это? Я не могу изменить его с Write на WriteLine в исходной программе командной строки, так как Write используется для запроса ввода.

Соответствующий код:

var startInfo = new ProcessStartInfo(ServerFile);
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;

ServerProc = new Process();
ServerProc.StartInfo = startInfo;
ServerProc.EnableRaisingEvents = true;
ServerProc.ErrorDataReceived += new DataReceivedEventHandler(ServerProc_ErrorDataReceived);
ServerProc.OutputDataReceived += new DataReceivedEventHandler(ServerProc_OutputDataReceived);

private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    Dispatcher.Invoke(new Action(() =>
    {
        ConsoleTextBlock.Text += e.Data + "\r\n";
        ConsoleScroll.ScrollToEnd();
    }));
}

private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Dispatcher.Invoke(new Action(() =>
    {
        ConsoleTextBlock.Text += e.Data + "\r\n";
        ConsoleScroll.ScrollToEnd();
    }));
}

1 Ответ

2 голосов
/ 03 июля 2011

Проблема, с которой вы столкнулись, заключается в том, что класс Process настроен для удобной линейно-ориентированной обработки событий процесса. Вы не можете использовать эту функцию, если вам нужно читать частичные строки, когда они выводятся.

Тем не менее, класс Process дает вам необходимые инструменты, если вам нужен более точный контроль над выходом, чем в линейных объектах. Если вы перенаправите вывод, то Process.StandardOutput - это StreamReader, и у вас есть весь API-интерфейс StreamReader, который вы можете использовать вместо необходимости читать целые строки.

Например, здесь посимвольное чтение стандартного вывода:

var start = DateTime.Now;
int n;
while ((n = ServerProc.StandardOutput.Read()) != -1)
{
    var c = (char)n;
    var delta = (DateTime.Now - start).TotalMilliseconds;
    Console.WriteLine("c = {0} (0x{1:X}) delta = {2}",
        char.IsWhiteSpace(c) ? '*' : c, n, delta);
}

Если мы запустим его в другой консольной программе, которая выдаст этот вывод:

Console.Write("abc");
Thread.Sleep(1000);
Console.WriteLine("def");

Он производит такой вывод:

c = a (0x61) delta = 44.0025
c = b (0x62) delta = 44.0025
c = c (0x63) delta = 44.0025
c = d (0x64) delta = 1109.0634
c = e (0x65) delta = 1110.0635
c = f (0x66) delta = 1110.0635
c = * (0xD) delta = 1110.0635
c = * (0xA) delta = 1110.0635

, который показывает, что "abc" был прочитан за одну секунду до остальной части строки.

Однако это не удобно, если вам нравится ориентированный на события ввод-вывод, уже предоставленный Process. Вы можете либо:

  • использовать асинхронный Stream API
  • использовать потоки, которые блокируют чтение

и, возможно, даже сверните свой собственный ввод-вывод на основе событий, который соответствует вашим потребностям.

Вы пишете программу, которая анализирует символьно-ориентированный вывод другой программы, и поэтому без полных строк вам понадобится какой-то тайм-аут, чтобы указать: «Теперь я удовлетворен тем, что программа на данный момент производит вывод». Это может быть легко или сложно в зависимости от того, насколько предсказуемым будет результат. Например, вы можете распознать приглашение, оканчивающееся на "?". Это зависит от вашей ситуации.

Дело в том, что вам придется использовать свойства StandardOutput и StandardError StreamReader, если вы хотите что-то отличное от линейно-ориентированного ввода / вывода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...