Process.Start не выводит полный вывод

У меня есть процесс P, который вызывает исполняемый файл PSEXEC и передает ему аргумент. Моя проблема в том, что вывод моей программы на С# отличается от того, когда я вызываю точно такую ​​же команду непосредственно в командную строку.

Вот результат, который я ожидаю (при запуске из CMD):

Server Name           Server Load
--------------------  ------------
601CTXD04             0
601CTXD05             0
...
601CTXP03             0

И вот фактический вывод (при запуске из моей программы):

Server Name           Server Load
--------------------  ------------
601CTXD04             0

Поэтому, когда я запускаю команду из своей программы на C#, я получаю только 1 сервер. Я называю процесс следующим образом:

p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = cServer.psexec; //Path to the PSEXEC executable
p.StartInfo.Arguments = "-accepteula \\\\601ctxp01 qfarm /load /continue";
p.Start();

string output = p.StandardOutput.ReadToEnd();
string[] lines = Regex.Split(output, "\\r\\n");

Я действительно не понимаю, почему та же самая команда, запущенная из CMD, не дает такого же результата при запуске из процесса C #. Пожалуйста, дайте мне знать, что я делаю неправильно, поскольку я в настоящее время не обращаю внимания на свою ошибку.


person MrRoy    schedule 20.11.2014    source источник
comment
попробуйте добавить p.WaitForExit() после p.Start()   -  person feiyun0112    schedule 20.11.2014
comment
Не используйте p.WaitForExit после p.Start()! если перенаправленный вывод записывает достаточно текста, чтобы заполнить поток, у вас возникнет тупиковая ситуация, и программа зависнет. Вы можете либо использовать p.WaitForExit(int32), либо вызвать его после прочтения вывода.   -  person James Ralston    schedule 20.11.2014
comment
Совет не звонить WaitForExit() сразу после звонка Start() верен. Однако здесь вообще нет смысла вызывать WaitForExit(). ReadToEnd() не вернется, пока поток не будет закрыт, что не произойдет, пока процесс не завершится.   -  person Peter Duniho    schedule 20.11.2014


Ответы (3)


Вам нужно вызвать p.WaitForExit() после p.StandardOutput.ReadToEnd(), иначе вы не получите весь вывод процесса. Не ставьте его сразу после p.Start() — вы можете зайти в тупик. См. http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput%28v=vs.110%29.aspx

person Simon Taylor    schedule 20.11.2014
comment
Я добавил p.WaitForExit() после string output = p.StandardOutput.ReadToEnd();, но он делает то же самое - я получаю только 1 строку вывода. - person MrRoy; 20.11.2014
comment
Есть ли какой-либо вывод на p.StandardError? - person Simon Taylor; 20.11.2014
comment
Я также пытался добавить p.WaitForExit() перед ReadToEnd, но это дает то же самое (только один вывод вместо всех) - person MrRoy; 20.11.2014
comment
Код ошибки 0 не обязательно означает отсутствие вывода стандартной ошибки. Перенаправление вывода psexec кажется вообще ненадежным, возможно, попробуйте перенаправить в файл. stackoverflow.com/questions/6812637/ - person Simon Taylor; 20.11.2014
comment
Код ошибки 0 исходит от команды qfarm, а не от самого psexec. Я мог бы перенаправить в файл, а затем прочитать файл, но это похоже на обходной путь, а не на исправление. Кроме того, намного сложнее выводить в файл и затем обрабатывать данные, чем просто выводить в строку, как я делаю сейчас. Если это единственный способ исправить это, то я сделаю это, но я сомневаюсь, что это так, поскольку у меня есть другие команды, использующие утилиту psexec, и все они работают хорошо. - person MrRoy; 20.11.2014
comment
Я попытался оставить CreateNoWindow равным false и посмотрел на результат. Оно работает. Итак, когда у меня есть RedirectStandardOutput = true, это когда у меня есть только одна строка - person MrRoy; 20.11.2014
comment
Этот ответ неверен. Метод ReadToEnd() будет блокироваться до тех пор, пока не будет достигнут конец потока. Добавление вызова (к чему-либо) после вызова ReadToEnd() не влияет на то, что возвращает ReadToEnd(). - person Peter Duniho; 20.11.2014
comment
@MrRoy: похоже, исполняемый файл, который вы используете, каким-то нестандартным образом использует стандартный вывод. Что это может быть, я не могу сказать. Если вы не можете придумать пример кода, который другие действительно могут попробовать, шансы того, что кто-то другой сможет понять проблему, низки. Является ли программа psexec.exe, которую вы используете, той же программой PsExec.exe от Sysinternals? Если да, то отсутствие окна может сбить его с толку. - person Peter Duniho; 20.11.2014
comment
Да, это PsExec.exe от Sysinternals. Я использую последнюю версию. Я также использую эту утилиту для других функций, и она работает хорошо, поэтому я не уверен, почему она не работает в данном случае. - person MrRoy; 20.11.2014
comment
@MrRoy: вы перенаправляете его стандартный вывод в другое место, и это работает? В этих случаях вы также выполняете команду qfarm? Или что-то другое? - person Peter Duniho; 20.11.2014
comment
Я использую PSLIST от Sysinternal, который выводит список процессов и перенаправляет стандартный вывод в строку. Он работает без каких-либо проблем. Я также использую PSEXEC в других местах для вызова команд на удаленных машинах, но я не перенаправляю вывод. - person MrRoy; 20.11.2014

Похоже, проблема была с самим PsExec (утилита Sysinternal), поскольку я пробовал альтернативу под названием PAExec, и та же команда работает нормально, поэтому вместо этого я использую ее в своем коде.

person MrRoy    schedule 20.11.2014

Обязательно иметь.

p.WaitForExit() 

метод после строки, где вы читаете вывод. Вот объяснение из MSDN: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput(v=vs.110).aspx

person James Ralston    schedule 20.11.2014
comment
Это неправильно. Метод ReadToEnd() будет блокироваться до тех пор, пока не будет достигнут конец потока. Добавление вызова (к чему-либо) после вызова ReadToEnd() не влияет на то, что возвращает ReadToEnd(). - person Peter Duniho; 20.11.2014
comment
Вы правы, в исходной строке не было WaitForExit перед вызовом для чтения потока. - person James Ralston; 20.11.2014