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 "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 로 설정 trueUseShellExecuteRedirectStandardOutput 해야 합니다. 그렇지 않으면 스트림에서 읽는 StandardOutput 경우 예외가 throw됩니다.

리디렉션된 스트림은 StandardOutput 동기적으로 또는 비동기적으로 읽을 수 있습니다. Read, ReadLine, 등의 ReadToEnd 메서드는 프로세스의 출력 스트림에서 동기 읽기 작업을 수행합니다. 이러한 동기 읽기 작업은 연결된 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.StandardError.ReadToEnd 를 호출 p.StandardOutput.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.

비동기 읽기 작업을 사용하여 이러한 종속성과 교착 상태 가능성을 방지할 수 있습니다. 또는 두 개의 스레드를 만들고 별도의 스레드에서 각 스트림의 출력을 읽어 교착 상태를 방지할 수 있습니다.

적용 대상

추가 정보