C #: построчно получить результат команды внешней оболочки - PullRequest
5 голосов
/ 19 августа 2011

Я пишу приложение Winform на C #, которое запускает второй процесс для выполнения команд оболочки, таких как «dir» и «ping».Я перенаправляю вывод второго процесса, чтобы мое приложение могло получить результат команды.Это примерно работает нормально.

Единственная проблема - мое приложение winform получает вывод командной строки целиком, а не построчно.Например, он должен дождаться завершения внешней команды ping (которая занимает много секунд или дольше), а затем сразу получить весь вывод (много строк).

То, что я хочу, - это приложение получаетвывод cmdline в режиме реального времени, т.е. по строкам, а не по блокам.Это выполнимо?

Я использую этот код для чтения вывода: while ((result = proc.StandardOutput.ReadLine ())! = Null)

Но это не работаетЯ ожидал.Заранее спасибо.

РЕДАКТИРОВАТЬ: вот код, который я использую:

    System.Diagnostics.ProcessStartInfo procStartInfo = new 
            System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);

    procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

    // The following commands are needed to redirect the standard output.
    procStartInfo.RedirectStandardOutput = true;
    procStartInfo.UseShellExecute = false;
    procStartInfo.CreateNoWindow = true;
    // Now we create a process, assign its ProcessStartInfo and start it
    System.Diagnostics.Process proc = new System.Diagnostics.Process();
    proc.StartInfo = procStartInfo;
    proc.Start();

    // Get the output into a string
    string result;
    try {
        while ((result = proc.StandardOutput.ReadLine()) != null)
        {
            AppendRtfText(result+"\n", Brushes.Black);
        }
    } // here I expect it to update the text box line by line in real time
      // but it does not.

Ответы [ 4 ]

3 голосов
/ 19 августа 2011

Посмотрите на пример в этой статье MSDN о том, как сделать чтение полностью асинхронным.

Кроме того, я ожидаю, что теперь ваш код будет читать построчно, но пользовательский интерфейс не получает времени на перерисовку (отсутствует Application.DoEvents (); после обновления RTFTextBox

2 голосов
/ 19 августа 2011

Вместо цикла с использованием while ((result = proc.StandardOutput.ReadLine()) != null) вы должны использовать:

...
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();

Это запустит асинхронное чтение строк, когда они поступят, затем вы обработаете строки, прочитанные e.Data в обработчике proc_DataReceived, так как вы используете BeginOutputReadline, e.Data будет строкой.

1 голос
/ 19 августа 2011
0 голосов
/ 02 июня 2014

У меня была та же проблема, и я обошел ее следующим. Я обнаружил, что если у меня была ошибка во внешнем приложении, я вообще не получал вывод, используя метод ReadToEnd(), поэтому переключился на построчное считывание потоков. Будет переключаться, чтобы использовать ответ, предоставленный Saa'd, хотя это выглядит как правильный способ справиться с этим.

Также найдено это решение: c # соглашение о кодировании public / private context , которое одновременно обеспечивает обработку ошибок и дает более полное объяснение использования externalApp.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);

Process externalApp = new Process();
        externalApp.StartInfo.FileName = config.ExternalApps + @"\location\DeleteApp.exe";
        externalApp.StartInfo.Arguments = Directory.GetCurrentDirectory() + @"\..\..\..\project\argumentsForDeleteApp.xml";
        externalApp.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        externalApp.StartInfo.UseShellExecute = false;
        externalApp.StartInfo.RedirectStandardOutput = true;
        Console.Out.WriteLine(DateTime.UtcNow.ToLocalTime().ToString() +
            ":######    External app: " + externalApp.StartInfo.FileName + " -      START");
        externalApp.Start();
        using (StreamReader reader = externalApp.StandardOutput)
        {
            while (!reader.EndOfStream)
            {
                string result = reader.ReadLine();
                Console.Out.WriteLine(result);
            }
        }
        externalApp.WaitForExit();
...