ProcessStartInfo.RedirectStandardOutput 屬性
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
取得或設定值,表示應用程式的文字輸出是否寫入至 StandardOutput 資料流。
public:
property bool RedirectStandardOutput { bool get(); void set(bool value); };
public bool RedirectStandardOutput { get; set; }
member this.RedirectStandardOutput : bool with get, set
Public Property RedirectStandardOutput As Boolean
屬性值
如果輸出應該寫入至 StandardOutput,則為 true
,否則為 false
。 預設為 false
。
範例
// Run "cl.exe /cld stdstr.cpp /link /out:sample.exe". UseShellExecute is false because we're specifying
// an executable directly and in this case depending on it being in a PATH folder. By setting
// RedirectStandardOutput to true, the output of cl.exe is directed to the Process.StandardOutput stream
// which is then displayed in this console window directly.
Process^ compiler = gcnew Process;
compiler->StartInfo->FileName = "cl.exe";
compiler->StartInfo->Arguments = "/clr stdstr.cpp /link /out:sample.exe";
compiler->StartInfo->UseShellExecute = false;
compiler->StartInfo->RedirectStandardOutput = true;
compiler->Start();
Console::WriteLine( compiler->StandardOutput->ReadToEnd() );
compiler->WaitForExit();
// Run "csc.exe /r:System.dll /out:sample.exe stdstr.cs". UseShellExecute is false because we're specifying
// an executable directly and in this case depending on it being in a PATH folder. By setting
// RedirectStandardOutput to true, the output of csc.exe is directed to the Process.StandardOutput stream
// which is then displayed in this console window directly.
using (Process compiler = new Process())
{
compiler.StartInfo.FileName = "csc.exe";
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();
Console.WriteLine(compiler.StandardOutput.ReadToEnd());
compiler.WaitForExit();
}
' Run "vbc.exe /reference:Microsoft.VisualBasic.dll /out:sample.exe stdstr.vb". UseShellExecute is False
' because we're specifying an executable directly and in this case depending on it being in a PATH folder.
' By setting RedirectStandardOutput to True, the output of csc.exe is directed to the Process.StandardOutput
' stream which is then displayed in this console window directly.
Using compiler As New Process()
compiler.StartInfo.FileName = "vbc.exe"
compiler.StartInfo.Arguments = "/reference:Microsoft.VisualBasic.dll /out:sample.exe stdstr.vb"
compiler.StartInfo.UseShellExecute = False
compiler.StartInfo.RedirectStandardOutput = True
compiler.Start()
Console.WriteLine(compiler.StandardOutput.ReadToEnd())
compiler.WaitForExit()
End Using
備註
Process當 將文字寫入至其標準數據流時,該文字通常會顯示在控制臺上。 藉由將 設定 RedirectStandardOutput 為 true
以重新導向 StandardOutput 數據流,您可以操作或隱藏進程的輸出。 例如,您可以篩選文字、以不同的方式格式化,或將輸出寫入主控台和指定的記錄檔。
注意
如果您想要設定為 ,則必須將 設定UseShellExecutefalse
RedirectStandardOutput為。true
否則,從 StandardOutput 數據流讀取會擲回例外狀況。
重新導向 StandardOutput 數據流可以同步或異步讀取。 、 ReadLine和 ReadToEnd 等Read方法會在行程的輸出數據流上執行同步讀取作業。 這些同步讀取作業在相關聯的 Process 寫入至其 StandardOutput 數據流之前不會完成,或關閉數據流。
相反地, BeginOutputReadLine 在數據流上 StandardOutput 啟動異步讀取作業。 這個方法會啟用指定的事件處理程式 (查看 OutputDataReceived 數據流輸出的) ,並立即返回呼叫端,這可以在數據流輸出導向事件處理程式時執行其他工作。
注意
正在處理異步輸出的應用程式應該呼叫 WaitForExit 方法,以確保已清除輸出緩衝區。
同步讀取作業會在從 StandardOutput 數據流讀取的呼叫端與寫入該數據流的子進程之間建立相依性。 這些相依性可能會導致死結狀況。 當呼叫端從子進程的重新導向數據流讀取時,它會相依於子系。 呼叫端會等候讀取作業,直到子系寫入數據流或關閉數據流為止。 當子進程寫入足夠的數據以填滿其重新導向的數據流時,它會相依於父代。 子進程會等候下一個寫入作業,直到父系從完整數據流讀取或關閉數據流為止。 當呼叫端和子進程等候彼此完成作業,而且兩者都無法繼續時,死結條件就會產生。 您可以藉由評估呼叫端與子進程之間的相依性來避免死結。
本節的最後兩個範例會 Start 使用 方法來啟動 名為Write500Lines.exe的可執行檔。 下列範例包含其原始程式碼。
using System;
using System.IO;
public class Example3
{
public static void Main()
{
for (int ctr = 0; ctr < 500; ctr++)
Console.WriteLine($"Line {ctr + 1} of 500 written: {ctr + 1/500.0:P2}");
Console.Error.WriteLine("\nSuccessfully wrote 500 lines.\n");
}
}
// The example displays the following output:
// The last 50 characters in the output stream are:
// ' 49,800.20%
// Line 500 of 500 written: 49,900.20%
//'
//
// Error stream: Successfully wrote 500 lines.
Imports System.IO
Public Module Example
Public Sub Main()
For ctr As Integer = 0 To 499
Console.WriteLine($"Line {ctr + 1} of 500 written: {ctr + 1/500.0:P2}")
Next
Console.Error.WriteLine($"{vbCrLf}Successfully wrote 500 lines.{vbCrLf}")
End Sub
End Module
' The example displays the following output:
' The last 50 characters in the output stream are:
' ' 49,800.20%
' Line 500 of 500 written: 49,900.20%
'
'
' Error stream: Successfully wrote 500 lines.
下列範例示範如何從重新導向的數據流讀取,並等候子進程結束。 此範例會藉由在 之前p.WaitForExit
呼叫 p.StandardOutput.ReadToEnd
來避免死結條件。 如果父進程在 之前p.StandardOutput.ReadToEnd
呼叫 p.WaitForExit
,且子進程寫入足夠的文字以填滿重新導向數據流,則死結條件可能會產生。 父進程會無限期等候子進程結束。 子進程會無限期等候父系從完整 StandardOutput 數據流讀取。
using System;
using System.Diagnostics;
public class Example2
{
public static void Main()
{
var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// To avoid deadlocks, always read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine($"The last 50 characters in the output stream are:\n'{output.Substring(output.Length - 50)}'");
}
}
// The example displays the following output:
// Successfully wrote 500 lines.
//
// The last 50 characters in the output stream are:
// ' 49,800.20%
// Line 500 of 500 written: 49,900.20%
// '
Imports System.Diagnostics'
Public Module Example
Public Sub Main()
Dim p As New Process()
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
p.StartInfo.FileName = "Write500Lines.exe"
p.Start()
' To avoid deadlocks, always read the output stream first and then wait.
Dim output As String = p.StandardOutput.ReadToEnd()
p.WaitForExit()
Console.WriteLine($"The last 50 characters in the output stream are:\n'{output.Substring(output.Length - 50)}'")
End Sub
End Module
' The example displays the following output:
' Successfully wrote 500 lines.
'
' The last 50 characters in the output stream are:
' ' 49,800.20%
' Line 500 of 500 written: 49,900.20%
' '
當您從標準輸出和標準錯誤數據流讀取所有文字時,會出現類似的問題。 下列範例會在這兩個數據流上執行讀取作業。 它會在數據流上 StandardError 執行異步讀取作業,以避免死結狀況。 如果父行程呼叫 p.StandardOutput.ReadToEnd
後面接著 p.StandardError.ReadToEnd
,且子進程會寫入足夠的文字來填滿其錯誤數據流,則死結條件會產生。 父進程會無限期等候子進程關閉其 StandardOutput 數據流。 子進程會無限期等候父系從完整 StandardError 數據流讀取。
using System;
using System.Diagnostics;
public class Example
{
public static void Main()
{
var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
string eOut = null;
p.StartInfo.RedirectStandardError = true;
p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
{ eOut += e.Data; });
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// To avoid deadlocks, use an asynchronous read operation on at least one of the streams.
p.BeginErrorReadLine();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine($"The last 50 characters in the output stream are:\n'{output.Substring(output.Length - 50)}'");
Console.WriteLine($"\nError stream: {eOut}");
}
}
// The example displays the following output:
// The last 50 characters in the output stream are:
// ' 49,800.20%
// Line 500 of 500 written: 49,900.20%
// '
//
// Error stream: Successfully wrote 500 lines.
Imports System.Diagnostics
Public Module Example
Public Sub Main()
Dim p As New Process()
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
Dim eOut As String = Nothing
p.StartInfo.RedirectStandardError = True
AddHandler p.ErrorDataReceived, Sub(sender, e) eOut += e.Data
p.StartInfo.FileName = "Write500Lines.exe"
p.Start()
' To avoid deadlocks, use an asynchronous read operation on at least one of the streams.
p.BeginErrorReadLine()
Dim output As String = p.StandardOutput.ReadToEnd()
p.WaitForExit()
Console.WriteLine($"The last 50 characters in the output stream are:{vbCrLf}'{output.Substring(output.Length - 50)}'")
Console.WriteLine($"{vbCrLf}Error stream: {eOut}")
End Sub
End Module
' The example displays the following output:
' The last 50 characters in the output stream are:
' ' 49,800.20%
' Line 500 of 500 written: 49,900.20%
' '
'
' Error stream: Successfully wrote 500 lines.
您可以使用異步讀取作業來避免這些相依性及其死結的可能性。 或者,您可以建立兩個線程並在個別線程上讀取每個數據流的輸出,以避免死結狀況。