Определение конца вывода консоли


Я получаю вывод консоли в своем приложении. Я использую код из здесь (принятое решение). Но я никогда не получаю null в моем OutputDataReceived. Вместо этого у меня есть строка .Пустое в конце вывода. Было бы правильно использовать строку.NullOrEmpty вместо простого сравнения с null?

static void Main(string[] args)
        {
            var command = @"wmic cpu get loadpercentage";
            using (Process process = new Process())
            {
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardError = true;

                StringBuilder output = new StringBuilder();
                StringBuilder error = new StringBuilder();

                using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                {
                    process.OutputDataReceived += (sndr, a) =>
                    {
                        if (a.Data == null)
                        {
                            outputWaitHandle.Set();
                        }
                        else
                        {
                            output.AppendLine(a.Data);
                        }
                    };
                    process.ErrorDataReceived += (sndr, a) =>
                    {
                        if (a.Data == null)
                        {
                            errorWaitHandle.Set();
                        }
                        else
                        {
                            error.AppendLine(a.Data);
                        }
                    };

                    process.Start();
                    process.BeginOutputReadLine();    
                    outputWaitHandle.WaitOne();

                    string path = "Test.txt";
                    using (StreamWriter sw = File.Exists(path) ? File.AppendText(path) : File.CreateText(path))
                    {
                        sw.WriteLine(String.Format("{0}, {1}", DateTime.Now, output));

                    }

                }
            }
        }

Update: похоже, что он не будет работать многострочный вывод. Вопрос в том, почему в A. Data

1 2

1 ответ:

Стандартный выходной поток завершается только с завершением самого процесса. Обратите внимание, что здесь "процесс" означает процесс, запущенный cmd.exe. Этот процесс может запускать другие процессы, но они имеют свой собственный стандартный выходной поток, и хотя stdout этих процессов будет завершен, когда они сами завершатся, ничто из этого не влияет на stdout родительского процесса cmd.exe.

Если вы хотите запустить процесс, который запускает различные другие процессы, эмулируя пользовательский ввод в cmd.exe, затем вам также придется эмулировать взаимодействие с пользователем, которое распознает и реагирует на последнюю выполняемую команду.

Представьте себя на месте реального пользователя и подумайте о том, как он справляется с ситуацией. Когда они выполняют команду в окне командной строки, закрывается ли это окно по завершении выполнения команды? № Получают ли они какие-либо указания на то, что команда выполнена? Что-то вроде того. Во-первых, они предположительно ожидают, что выходные данные команды будут соответствовать какой-то определенный формат, который часто будет включать в себя какой-то индикатор того, что команда выполнила. Во-вторых, в окне командной строки появится новая строка (то есть" строка "во фразе"command-prompt"). Обратите внимание, что вредоносная команда может вычислить, как выглядит текущая подсказка, и подделать ее. Но это необычно, и, вероятно, у вас достаточно контроля над командами, которые вы выдаете, чтобы избежать этого. Таким образом, один из подходов заключается в том, чтобы просто обрабатывать выходные данные по мере их появления и обнаруживать новые приглашение, которое появляется, когда команда завершена.

Если это не кажется достаточно надежным, то вам придется обрабатывать каждую команду индивидуально, интерпретируя выходные данные команды и распознавая, когда эта команда достигла конца своих выходных данных, только из содержимого в этих выходных данных.

Наконец, обратите внимание, что вы можете использовать класс Process для выполнения самих команд. Вам не нужно cmd.exe, чтобы сделать это. И если вы выполняете каждую команду как отдельный процесс вы сами, то Вы делаете заканчиваете получать уведомление о завершении процесса через конец потока stdout для каждого процесса.