當 Process 將文本寫入其標准流中時,通常將在控制台上顯示該文本。通過重定向 StandardOutput 流,可以操作或取消進程的輸出。例如,可以篩選文本、用不同方式將其格式化,也可以將輸出同時寫入控制台和指定的日志文件中。有兩種方式:同步、異步。
1. 先說同步方法,這種方法網上有很多例子,廢話少說,貼上代碼大家一看就明白了:
Processprocess = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = false; // 是否使用外殼程序
process.StartInfo.CreateNoWindow = true; //是否在新窗口中啟動該進程的值
process.StartInfo.RedirectStandardInput = true; // 重定向輸入流
//process.StartInfo.RedirectStandardOutput= true; //重定向輸出流
//process.StartInfo.RedirectStandardError= true; //重定向錯誤流
stringstrCmd = "ping www.163.com /r/n";
strCmd += "exit";
process.Start();
process.StandardInput.WriteLine(strCmd);
stringoutput = process.StandardOutput.ReadToEnd();//獲取輸出信息
process.WaitForExit();
int n =process.ExitCode; // n 為進程執行返回值
process.Close();
可以同步或異步讀取重定向的 StandardOutput 流。Read、ReadLine 和 ReadToEnd 等方法對進程的輸出流執行同步讀取操作。這些同步讀取操作只有在關聯的 Process 寫入其StandardOutput 流或關閉該流后才能完成。
同步讀取操作在讀取 StandardOutput 流的調用方及寫入該流中的子進程之間引入一個依賴項。這些 依賴項可能導致產生死鎖情況。調用方讀取子進程的重定向流時依賴於該子進程。調用方將等待讀取操作,直到子進程寫入流或關閉流為止。子進程寫入足夠多的數 據以填充重定向流的時間依賴於父進程。子進程將等待下一次寫操作,直到父進程讀取了全部流或關閉該流為止。當調用方和子進程相互等待對方完成操作時,就會 產生死鎖情況,使雙方都無法繼續執行操作。可以通過計算調用方和子進程之間的依賴項從而避免出現死鎖情況。
2. 再來說一下異步方法
使用事件和委托,進程有2個事件OutputDataReceived、OutputDataReceived。
我們可以注冊這2個事件,使該進程在往Output和error流中填充數據時,調用相應的事件響應函數,及時處理流中數據,從而避免流被填滿而發生的死鎖情況,在WaitForExit之前調用BeginOutputReadLine 或者BeginErrorReadLine 開始異步讀取。此方法會為流輸出啟用一個指定的事件處理程序並立即返回到調用方,這樣當流輸出被定向到該事件處理程序時,調用方還可以執行其他操作。
注意 |
若要使用 StandardOutput,必須將 ProcessStartInfo.UseShellExecute 設置為 false,並且將 ProcessStartInfo.RedirectStandardOutput 設置為 true。否則,讀取StandardOutput 流時將引發異常。 |
// using System.Diagnostics;
// 運行新進程
ProcessStartInfostartInfo =newProcessStartInfo(exeName);
startInfo.CreateNoWindow = true; //不創建窗口
startInfo.UseShellExecute = false;//不使用系統外殼程序啟動,重定向輸出的話必須設為false
startInfo.RedirectStandardOutput = true; //重定向輸出,而不是默認的顯示在dos控制台上
startInfo.RedirectStandardError = true;
try
{
Processprocess = Process.Start(startInfo);
process.OutputDataReceived += (s, _e)=> Console.WriteLine(_e.Data);
process.ErrorDataReceived += (s, _e) =>Console.WriteLine(_e.Data);
//當EnableRaisingEvents為true,進程退出時Process會調用下面的委托函數
process.Exited += (s, _e) => Console.WriteLine("Exited with " + _process.ExitCode);
process.EnableRaisingEvents = true;
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
catch (Exception e)
{
Console.WriteLine(ex.Message);
}
3. 注意事項
不能對同一個重定向流混合使用異步和同步讀取操作。在異步或同步模式下打開 Process 的重定向流后,對該流的所有進一步的讀取操作都必須在同一模式下進行。例如,不要對StandardOutput 流調用BeginOutputReadLine 后接着調用ReadLine,反之亦然。但是,可以在不同的模式下讀取兩個不同的流。例如,可以先調用BeginOutputReadLine,然后再為StandardError 流調用 ReadLine。