Команда tasklist не завершится, если RedirectStandardOutput имеет значение true - PullRequest
0 голосов
/ 06 октября 2019

Я пытаюсь выполнить команду и ждать ее завершения:

Process proc = new Process();

proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c tasklist";
proc.Start();

proc.WaitForExit();
return;

Однако команда tasklist никогда не завершится, если для RedirectStandardOutput установлено значение true.

Если я установлю для RedirectStandardOutput значение false или изменим команду на /c whoami, она почти сразу завершится.

Есть идеи?

1 Ответ

1 голос
/ 06 октября 2019

Этот фрагмент должен работать нормально:

Process proc = new Process();

proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c tasklist";
proc.Start();

var output = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();

Console.WriteLine(output);
return;

Без чтения вывода tasklist процесс ожидает, пока родительский процесс не прочитает вывод, в соответствии с MSDN

Может возникнуть условие взаимоблокировки, если родительский процесс вызывает p.WaitForExit до p.StandardOutput.ReadToEnd, а дочерний процесс записывает достаточно текста, чтобы заполнить перенаправленный поток. Родительский процесс будет бесконечно ждать завершения дочернего процесса. Дочерний процесс будет бесконечно ждать, пока родительский файл прочитает из полного потока * 1012.

Вы также можете выполнить асинхронное чтение выходных данных процесса (и ограничить время ожидания процесса для времени ожидания выхода), например,this

Process proc = new Process();
StringBuilder output = new StringBuilder();

proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c tasklist";
proc.OutputDataReceived += (s, e) =>
{
    output.Append(e.Data).Append("\n");
};
proc.ErrorDataReceived += (s, e) =>
{
    output.Append(e.Data).Append("\n");
};

proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit(100);

Console.WriteLine(output);

return; 

Кроме того, если вы собираетесь перенаправить оба потока (с ошибкой и выходом), вы прочитали хотя бы один из них асинхронно из-за взаимных блокировок (ссылка на MSDN показывает пример)

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