ProcessStartInfo.RedirectStandardError Свойство

Определение

Возвращает или задает значение, указывающее, записываются ли выходные данные ошибки приложения в StandardError поток.

public:
 property bool RedirectStandardError { bool get(); void set(bool value); };
public bool RedirectStandardError { get; set; }
member this.RedirectStandardError : bool with get, set
Public Property RedirectStandardError As Boolean

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

trueЗначение , StandardErrorесли выходные данные ошибки должны быть записаны falseв ; в противном случае . Значение по умолчанию — false.

Примеры

В следующем примере команда используется net use вместе с предоставленным пользователем аргументом для сопоставления сетевого ресурса. Затем он считывает стандартный поток ошибок net команды и записывает его в консоль.

using (Process myProcess = new Process())
{
    ProcessStartInfo myProcessStartInfo = new ProcessStartInfo("net ", "use " + args[0]);

    myProcessStartInfo.UseShellExecute = false;
    myProcessStartInfo.RedirectStandardError = true;
    myProcess.StartInfo = myProcessStartInfo;
    myProcess.Start();

    StreamReader myStreamReader = myProcess.StandardError;
    // Read the standard error of net.exe and write it on to console.
    Console.WriteLine(myStreamReader.ReadLine());
}
Using myProcess As New Process()
    Dim myProcessStartInfo As New ProcessStartInfo("net ", "use " + args(0))

    myProcessStartInfo.UseShellExecute = False
    myProcessStartInfo.RedirectStandardError = True
    myProcess.StartInfo = myProcessStartInfo
    myProcess.Start()

    Dim myStreamReader As StreamReader = myProcess.StandardError
    ' Read the standard error of net.exe and write it on to console.
    Console.WriteLine(myStreamReader.ReadLine())
End Using

Комментарии

Когда текст записывается в стандартный Process поток ошибок, этот текст обычно отображается в консоли. Перенаправляя StandardError поток, вы можете управлять или подавлять выходные данные ошибок процесса. Например, можно отфильтровать текст, отформатировать его по-разному или записать выходные данные в консоль и в указанный файл журнала.

Note

Необходимо задать UseShellExecute значение, если вы хотите задать значение falseRedirectStandardErrortrue . В противном случае чтение из StandardError потока вызывает исключение.

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

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

Note

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

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

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

using System;
using System.Diagnostics;

public class Example
{
   public static void Main()
   {
      var p = new Process();  
      p.StartInfo.UseShellExecute = false;  
      p.StartInfo.RedirectStandardError = true;  
      p.StartInfo.FileName = "Write500Lines.exe";  
      p.Start();  

      // To avoid deadlocks, always read the output stream first and then wait.  
      string output = p.StandardError.ReadToEnd();  
      p.WaitForExit();

      Console.WriteLine($"\nError stream: {output}");
   }
}
// The end of the output produced by the example includes the following:
//      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.RedirectStandardError = 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.StandardError.ReadToEnd()  
        p.WaitForExit()

        Console.WriteLine($"{vbCrLf}Error stream: {output}")
    End Sub
End Module
' The end of the output produced by the example includes the following:
'      Error stream:
'      Successfully wrote 500 lines.

При чтении всего текста из стандартных выходных и стандартных потоков ошибок возникает аналогичная проблема. Следующий код C#, например, выполняет операцию чтения в обоих потоках. Это позволяет избежать взаимоблокировки путем выполнения асинхронных операций чтения в потоке 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.

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

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

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