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

プロパティ値

出力を 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が標準ストリームにテキストを書き込むとき、そのテキストは通常コンソールに表示されます。 を にtrue設定RedirectStandardOutputしてストリームをStandardOutputリダイレクトすることで、プロセスの出力を操作または抑制できます。 たとえば、テキストをフィルター処理したり、書式を変更したり、コンソールと指定されたログ ファイルの両方に出力を書き込んだりできます。

注意

を にfalse設定UseShellExecuteする場合は、 を に設定RedirectStandardOutputするtrue必要があります。 それ以外の場合、ストリームからの読み取り StandardOutput では例外がスローされます。

リダイレクトされた StandardOutput ストリームは、同期的または非同期的に読み取ることができます。 、、 などのReadReadLineメソッドは、ReadToEndプロセスの出力ストリームに対して同期読み取り操作を実行します。 これらの同期読み取り操作は、関連付けられている Process がストリームへの書き込みを行うか、ストリームを StandardOutput 閉じるまで完了しません。

これに対し、 はストリーム BeginOutputReadLine に対する非同期読み取り操作を StandardOutput 開始します。 このメソッドは、ストリーム出力に対して指定されたイベント ハンドラー (を参照 OutputDataReceived) を有効にし、すぐに呼び出し元に戻り、ストリーム出力がイベント ハンドラーに送信されている間に他の作業を実行できます。

注意

非同期出力を処理しているアプリケーションは、 メソッドを WaitForExit 呼び出して、出力バッファーがフラッシュされていることを確認する必要があります。

同期読み取り操作では、ストリームからの呼び出し元の読み取りと、 StandardOutput そのストリームへの書き込み子プロセスとの間に依存関係が発生します。 これらの依存関係により、デッドロック状態が発生する可能性があります。 呼び出し元が子プロセスのリダイレクトされたストリームから読み取ると、子プロセスに依存します。 呼び出し元は、子がストリームに書き込むか、ストリームを閉じるまで読み取り操作を待機します。 子プロセスは、リダイレクトされたストリームを埋めるのに十分なデータを書き込むとき、親に依存します。 子プロセスは、親がフル ストリームから読み取るか、ストリームを閉じるまで、次の書き込み操作を待機します。 デッドロック状態は、呼び出し元と子プロセスが互いに操作の完了を待機し、どちらも続行できない場合に発生します。 呼び出し元と子プロセスの間の依存関係を評価することで、デッドロックを回避できます。

このセクションの最後の 2 つの例では、 メソッドを 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.

非同期読み取り操作を使用して、これらの依存関係とそのデッドロックの可能性を回避できます。 または、2 つのスレッドを作成し、別のスレッドで各ストリームの出力を読み取ることで、デッドロック状態を回避できます。

適用対象

こちらもご覧ください