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(); 

如何将两者结合起来读取所有输入,而不是陷入死锁并且如果运行过程出错则超时?

如果输出缓冲区填充了超过4KB的数据,则此技术将挂起。 更简单的方法是注册代理,以便在将某些内容写入输出流时得到通知。 我之前在另一篇文章中已经提出了这个方法 :

 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(); 

您不必将两者结合起来 – 当输出发送到StandardOutput时, Process类会触发一个事件 – OutputDataReceived

如果您订阅了该事件,您将能够在输出到达时读取输出,并且在主程序循环中您仍然可以超时。

您可以尝试将第一种方法修改为这样的方法

 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); 

编辑:为清楚起见删除了error handling。

只需将WaitForExit()调用下面的第一个示例中的所有内容添加到第二个示例中。