語言

ProcessStartInfo.RedirectStandardOutput 屬性

定義

取得或設定一個值,指示應用程式的文字輸出是否寫入 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

屬性值

true若輸出應寫入StandardOutput;否則,。 false 預設值為 false。

範例

// 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

備註

當 A Process 寫入其標準串流文字時,該文字通常會顯示在主控台上。 透過設定 RedirectStandardOutput 為 true 來重新導向串流, StandardOutput 你可以操作或抑制程序的輸出。 例如,你可以篩選文字、不同格式化,或將輸出寫入主控台與指定的日誌檔。

Note

如果你想設定UseShellExecute為 false,必須設定RedirectStandardOutput為 true 。 否則,從 StandardOutput 串流讀取會拋出例外。

重 StandardOutput 定向的串流可以同步或非同步讀取。 像 、 Read、 ReadLine 等方法ReadToEnd對程序的輸出串流執行同步讀取操作。 這些同步讀取操作直到相關 Process 寫入者寫入其 StandardOutput 串流或關閉串流後才會完成。

相較之下,開始 BeginOutputReadLine 對 StandardOutput 串流進行非同步讀取操作。 此方法啟用指定的事件處理程序(見 OutputDataReceived),用於串流輸出,並立即回傳給呼叫者,呼叫者在串流輸出導向事件處理程序時可執行其他工作。

Note

處理非同步輸出的應用程式應呼叫該 WaitForExit 方法,以確保輸出緩衝區已被清除。

同步讀取操作會產生呼叫者從串流讀取 StandardOutput 與子程序寫入該串流之間的依賴關係。 這些依賴性可能導致僵局。 當呼叫者從子程序的重定向串流讀取時,該程序依賴於子程序。 呼叫者等待讀取操作,直到子程式寫入串流或關閉串流。 當子程序寫入足夠資料填滿其重定向的串流時,它依賴父程序。 子程序會等待下一次寫入操作,直到父程序從完整串流讀取或關閉串流。 當呼叫者與子程序彼此等待完成操作,且雙方無法繼續時,就會產生死結狀態。 你可以透過評估呼叫者與子程序之間的依賴關係來避免僵局。

本節最後兩個範例使用 Start 了啟動名為 Write500Lines.exe的可執行檔的方法。 以下範例包含其原始碼。

using System;

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:
//      Line 1 of 500 written: 0,20%
//      Line 2 of 500 written: 0,40%
//      Line 3 of 500 written: 0,60%
//      ...
//      Line 498 of 500 written: 99,60%
//      Line 499 of 500 written: 99,80%
//      Line 500 of 500 written: 100,00%
//
//      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:
'      Line 1 of 500 written 0,20%
'      Line 2 of 500 written: 0,40%
'      Line 3 of 500 written: 0,60%
'      ...
'      Line 498 of 500 written: 99,60%
'      Line 499 of 500 written: 99,80%
'      Line 500 of 500 written: 100,00%
'
'      Successfully wrote 500 lines.

以下範例展示了如何從重定向的串流讀取並等待子程序退出。 本範例透過在 之前p.StandardOutput.ReadToEnd呼叫p.WaitForExit,避免了死結條件。 如果父程序在前p.WaitForExit段呼叫p.StandardOutput.ReadToEnd,而子程序寫入足夠文字填滿重定向串流,則可能造成死結狀態。 父程序會無限期等待子程序退出。 子程序會無限期等待家長從完整 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:
//      'ritten: 99,80%
//      Line 500 of 500 written: 100,00%
//      '
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:
'      'ritten: 99,80%
'      Line 500 of 500 written: 100,00%
'      '

當你同時閱讀標準輸出和標準錯誤流的所有文字時,也會有類似的問題。 以下範例對兩個串流執行讀取操作。 它透過對串流執行非同步讀取操作 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:
//      'ritten: 99,80%
//      Line 500 of 500 written: 100,00%
//      '
//
//      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:
'      'ritten: 99,80%
'      Line 500 of 500 written: 100,00%
'      '
'
'      Error stream: Successfully wrote 500 lines.

你可以使用非同步讀取操作來避免這些相依性及其死結風險。 或者,你也可以透過建立兩個執行緒,並在獨立執行緒讀取每個串流的輸出來避免死結。

適用於

另請參閱