c # ProcessStartInfo.Start – чтение вывода, но с таймаутом

Если вы хотите запустить другой процесс и подождать (с тайм-аутом), чтобы закончить, вы можете использовать следующее (из MSDN) .

//Set a time-out value. int timeOut=5000; //Get path to system folder. string sysFolder= Environment.GetFolderPath(Environment.SpecialFolder.System); //Create a new process info structure. ProcessStartInfo pInfo = new ProcessStartInfo(); //Set file name to open. pInfo.FileName = sysFolder + @"\eula.txt"; //Start the process. Process p = Process.Start(pInfo); //Wait for window to finish loading. p.WaitForInputIdle(); //Wait for the process to exit or time out. p.WaitForExit(timeOut); //Check to see if the process is still running. if (p.HasExited == false) //Process is still running. //Test to see if the process is hung up. if (p.Responding) //Process was responding; close the main window. p.CloseMainWindow(); else //Process was not responding; force the process to close. p.Kill(); MessageBox.Show("Code continuing..."); 

Если вы хотите запустить другой процесс и прочитать его вывод, вы можете использовать следующий шаблон (из SO)

 // 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 Кбайт данных. Более надежным способом является регистрация делегатов для уведомления, когда что-то записывается в выходной stream. Я уже предлагал этот метод раньше в другом посте :

 ProcessStartInfo processInfo = new ProcessStartInfo("Write500Lines.exe"); processInfo.ErrorDialog = false; processInfo.UseShellExecute = false; processInfo.RedirectStandardOutput = true; processInfo.RedirectStandardError = true; Process proc = Process.Start(processInfo); // You can pass any delegate that matches the appropriate // signature to ErrorDataReceived and OutputDataReceived proc.ErrorDataReceived += (sender, errorLine) => { if (errorLine.Data != null) Trace.WriteLine(errorLine.Data); }; proc.OutputDataReceived += (sender, outputLine) => { if (outputLine.Data != null) Trace.WriteLine(outputLine.Data); }; proc.BeginErrorReadLine(); proc.BeginOutputReadLine(); proc.WaitForExit(); 

Вам не нужно комбинировать два – class Process имеет событие, которое срабатывает, когда вывод отправляется в StandardOutputOutputDataReceived .

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

вы можете попробовать изменить первый метод на что-то вроде этого

 Process p = Process.Start(pInfo); string output = string.Empty; Thread t = new Thread(() => output = p.StandardOutput.ReadToEnd() ); t.Start(); //Wait for window to finish loading. p.WaitForInputIdle(); //Wait for the process to exit or time out. p.WaitForExit(timeOut); 
 void OpenWithStartInfo() { ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe", "Default2.aspx"); startInfo.WindowStyle = ProcessWindowStyle.Minimized; Process p = Process.Start(startInfo); p.WaitForInputIdle(); //p.WaitForExit(2); p.Kill(); } 

Вы также можете использовать APM, например:

Определите делегата для вызова ReadToEnd:

 private delegate string ReadToEndDelegate(); 

Затем используйте делегат для вызова метода следующим образом:

 ReadToEndDelegate asyncCall = reader.ReadToEnd; IAsyncResult asyncResult = asyncCall.BeginInvoke(null, null); asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(10)); asyncCall.EndInvoke(asyncResult); 

EDIT: обработка ошибок удалена для ясности.

Просто добавьте все из первого примера ниже WaitForExit() ко второму примеру.