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

Значение свойства

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 записывает текст в стандартный поток, этот текст обычно отображается в консоли. Если установить значение для RedirectStandardOutput true перенаправления StandardOutput потока, можно управлять выходом процесса или подавлять его вывод. Например, можно отфильтровать текст, отформатировать его по-другому или записать выходные данные как в консоль, так и в назначенный файл журнала.

Примечание

Необходимо задать значение UseShellExecute , false Если необходимо задать для значение RedirectStandardOutput true . В противном случае при чтении из StandardOutput потока возникает исключение.

Перенаправленный StandardOutput поток можно считывать синхронно или асинхронно. Такие методы Read , как, ReadLine и ReadToEnd выполняют синхронные операции чтения в потоке вывода процесса. Эти операции синхронного чтения не завершаются до тех пор, пока не будут вызваны связанные операции Process записи в свой StandardOutput поток или закрывается поток.

В отличие от этого, BeginOutputReadLine запускает асинхронные операции чтения в StandardOutput потоке. Этот метод включает назначенный обработчик событий (см. OutputDataReceived ) для выходного потока и немедленно возвращается вызывающему объекту, который может выполнять другие действия, пока потоковый выход направляется в обработчик событий.

Примечание

Приложение, обрабатывающее асинхронный вывод, должно вызывать WaitForExit метод, чтобы убедиться, что выходной буфер был сброшен.

Синхронные операции чтения представляют зависимость между вызывающим объектом чтения из StandardOutput потока и дочерним процессом, записывающим в этот поток. Эти зависимости могут вызвать условия взаимоблокировки. Когда вызывающий объект считывает данные из перенаправленного потока дочернего процесса, он зависит от дочернего объекта. Вызывающий объект ожидает операции чтения до тех пор, пока дочерние записи не будут записаны в поток или закроет поток. Когда дочерний процесс записывает достаточно данных для заполнения перенаправляемого потока, он зависит от родителя. Дочерний процесс ожидает следующей операции записи, пока родитель не считывает из полного потока или не закрывает поток. Условие взаимоблокировки вызывается, когда вызывающий и дочерний процесс ожидают друг друга для выполнения операции, и ни один из них не может продолжить работу. Можно избежать взаимоблокировок, оценивая зависимости между вызывающим и дочерним процессами.

В двух последних примерах в этом разделе используется Start метод для запуска исполняемого файла с именем Write500Lines.exe. В следующем примере содержится исходный код.

using System;
using System.IO;

public class Example
{
   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.StandardOutput.ReadToEnd до p.WaitForExit . Условие взаимоблокировки может быть получено, если родительский процесс вызывает p.WaitForExit до p.StandardOutput.ReadToEnd , а дочерний процесс записывает достаточно текста для заполнения перенаправленного потока. Родительский процесс ожидает завершения дочернего процесса в течение неограниченного времени. Дочерний процесс в течение неограниченного времени будет ждать, пока родительский поток не будет считаться из полного StandardOutput потока.

using System;
using System.Diagnostics;

public class Example
{
   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.

Асинхронные операции чтения можно использовать во избежание этих зависимостей и их возможных взаимоблокировок. Кроме того, можно избежать условия взаимоблокировки, создав два потока и прочитав выходные данные каждого потока в отдельном потоке.

Применяется к

См. также раздел