Process.StandardOutput 屬性

定義

取得用來讀取應用程式文字輸出的資料流。

C#
public System.IO.StreamReader StandardOutput { get; }
C#
[System.ComponentModel.Browsable(false)]
public System.IO.StreamReader StandardOutput { get; }

屬性值

StreamReader,可用來讀取應用程式的標準輸出資料流。

屬性

例外狀況

尚未針對重新導向定義 StandardOutput 資料流;請確定已將 RedirectStandardOutput 設為 true,且將 UseShellExecute 設為 false

-或-

已開啟 StandardOutput 資料流,用於搭配 BeginOutputReadLine() 的非同步讀取作業。

範例

下列範例會執行 ipconfig.exe 命令,並將其標準輸出重新導向至範例的控制台視窗。

C#
using System;
using System.IO;
using System.Diagnostics;

class StandardOutputExample
{
    public static void Main()
    {
        using (Process process = new Process())
        {
            process.StartInfo.FileName = "ipconfig.exe";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();

            // Synchronously read the standard output of the spawned process.
            StreamReader reader = process.StandardOutput;
            string output = reader.ReadToEnd();

            // Write the redirected output to this application's window.
            Console.WriteLine(output);

            process.WaitForExit();
        }

        Console.WriteLine("\n\nPress any key to exit.");
        Console.ReadLine();
    }
}

備註

Process當 將文字寫入至其標準數據流時,該文字通常會顯示在控制臺上。 藉由重新導向 StandardOutput 數據流,您可以操作或隱藏進程的輸出。 例如,您可以篩選文字、以不同的方式格式化,或將輸出寫入主控台和指定的記錄檔。

備註

若要使用 StandardOutput,您必須將 設定 ProcessStartInfo.UseShellExecutefalse,而且必須設定 ProcessStartInfo.RedirectStandardOutputtrue。 否則,從 StandardOutput 數據流讀取會擲回例外狀況。

重新導向 StandardOutput 的數據流可以同步或異步讀取。 、 ReadLineRead方法會在ReadToEnd進程的輸出數據流上執行同步讀取作業。 這些同步讀取作業在相關聯的 Process 數據流寫入 StandardOutput 或關閉數據流之前不會完成。

相反地, BeginOutputReadLine 會啟動數據流上的 StandardOutput 異步讀取作業。 這個方法會啟用數據流輸出的指定事件處理程式,並立即傳回給呼叫端,這可以在數據流輸出導向事件處理程式時執行其他工作。

同步讀取作業引進從 StandardOutput 數據流讀取的呼叫端與寫入該數據流的子進程之間的相依性。 這些相依性可能會導致死結狀況。 當呼叫端從子進程的重新導向數據流讀取時,它會相依於子進程。 呼叫端會等候讀取作業,直到子系寫入數據流或關閉數據流為止。 當子進程寫入足夠的數據以填滿其重新導向的數據流時,其相依於父代。 子進程會等候下一個寫入作業,直到父系從完整數據流讀取或關閉數據流為止。 當呼叫端和子進程彼此等候完成作業,且兩者都無法繼續時,死結條件就會產生。 您可以藉由評估呼叫端與子進程之間的相依性,以避免死結。

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

C#
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.

下列範例示範如何從重新導向的數據流讀取,並等候子進程結束。 此範例會藉由在 之前p.WaitForExit呼叫 p.StandardOutput.ReadToEnd 來避免死結狀況。 如果父進程在 之前p.StandardOutput.ReadToEnd呼叫 p.WaitForExit ,且子進程會寫入足夠的文字來填滿重新導向數據流,則死結條件可能會產生。 父進程會無限期等候子進程結束。 子進程會無限期地等候父代從完整 StandardOutput 數據流讀取。

C#
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%
//      '

當您從標準輸出和標準錯誤數據流讀取所有文字時,會有類似的問題。 下列範例會在這兩個數據流上執行讀取作業。 它會在數據流上 StandardError 執行異步讀取作業,以避免死結狀況。 如果父行程呼叫 p.StandardOutput.ReadToEnd 後面接著 p.StandardError.ReadToEnd ,且子進程會寫入足夠的文字來填滿其錯誤數據流,則死結條件會產生。 父進程會無限期等候子進程關閉其 StandardOutput 數據流。 子進程會無限期地等候父代從完整 StandardError 數據流讀取。

C#
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.

您可以使用異步讀取作業來避免這些相依性及其死結可能。 或者,您可以建立兩個線程並在個別線程上讀取每個數據流的輸出,以避免死結狀況。

備註

您無法在重新導向的數據流上混合異步和同步讀取作業。 在異步或同步模式中開啟的重新導向數據流 Process 之後,該數據流上的所有進一步讀取作業都必須處於相同的模式。 例如,請勿在BeginOutputReadLine數據流上StandardOutput呼叫 ReadLine ,反之亦然。 不過,您可以在不同的模式中讀取兩個不同的數據流。 例如,您可以呼叫 BeginOutputReadLine 資料流,然後呼叫 ReadLineStandardError

適用於

產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

另請參閱