Process.standardoutput.ReadToEnd() всегда пуст?
Я запускаю консольное приложение, но когда я перенаправляю стандартный вывод, я всегда ничего не получаю!
Когда я не перенаправляю его и устанавливаю CreateNoWindow
в false
, я вижу все правильно в консоли, но когда я перенаправляю его, StandardOutput.ReadToEnd()
всегда возвращает пустую строку.
Process cproc = new Process();
cproc.StartInfo.CreateNoWindow = true;
cproc.StartInfo.FileName = Dest;
cproc.StartInfo.RedirectStandardOutput = true;
cproc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
cproc.StartInfo.UseShellExecute = false;
cproc.EnableRaisingEvents = true;
cproc.Start();
cproc.Exited += new EventHandler(cproc_Exited);
while(!stop)
{
result += cproc.StandardOutput.ReadToEnd();
}
EventHandler cproc_exited
просто устанавливает stop
в true
. Может кто-нибудь объяснить, почему result
всегда string.Empty
?
Ответы
Ответ 1
Почему вы зацикливаетесь? Как только он будет прочитан до конца, он не сможет читать больше данных, не так ли?
Вы уверены, что текст фактически записывается в StandardOutput
, а не StandardError
?
(И да, очевидно, вы хотите установить RedirectStandardOutput
как true, а не false. Я предположил, что это всего лишь случай, когда вы копируете неправильную версию своего кода.)
EDIT: Как я уже сказал в комментариях, вы должны читать стандартный вывод и стандартную ошибку в отдельных потоках. Не ждите, пока процесс не выйдет - это может привести к тупиковой ситуации, когда вы ожидаете завершения процесса, но процесс блокирует попытку записи в stderr/stdout, потому что вы не читали из буфера.
В качестве альтернативы вы можете подписаться на события OutputDataReceived и ErrorDataReceived, чтобы избежать использования дополнительных потоков.
Ответ 2
Лучший способ для этого - перенаправить вывод и ждать событий:
// some of the flags are not needed
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.EnableRaisingEvents = true;
process.OutputDataReceived += process_OutputDataReceived;
process.ErrorDataReceived += process_OutputDataReceived;
process.Exited += process_Exited;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
void process_Exited(object sender, System.EventArgs e)
{
// do something when process terminates;
}
void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
// a line is writen to the out stream. you can use it like:
string s = e.Data;
}
void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
// a line is writen to the out stream. you can use it like:
string s = e.Data;
}
Ответ 3
У вас есть перенаправление стандартного отключенного. Попробуйте изменить
cproc.StartInfo.RedirectStandardOutput = false;
в
cproc.StartInfo.RedirectStandardOutput = true;
Работает ли для вас следующий образец MSDN?
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Ответ 4
Избавьтесь от цикла и переместите вызов на ReadToEnd
на cproc_Exited
.