Поделиться через


Process.StandardError Свойство

Определение

Получает поток, используемый для чтения вывода ошибок приложения.

public:
 property System::IO::StreamReader ^ StandardError { System::IO::StreamReader ^ get(); };
public System.IO.StreamReader StandardError { get; }
[System.ComponentModel.Browsable(false)]
public System.IO.StreamReader StandardError { get; }
member this.StandardError : System.IO.StreamReader
[<System.ComponentModel.Browsable(false)>]
member this.StandardError : System.IO.StreamReader
Public ReadOnly Property StandardError As StreamReader

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

Объект StreamReader, используемый для чтения стандартного потока ошибок приложения.

Атрибуты

Исключения

Поток StandardError не был определен для переадресации. Убедитесь, что для RedirectStandardError задано true, а для UseShellExecutefalse.

-или-

Поток StandardError был открыт для асинхронных операций чтения с BeginErrorReadLine().

Примеры

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

Process^ myProcess = gcnew Process;
ProcessStartInfo^ myProcessStartInfo = gcnew ProcessStartInfo( "net ",String::Concat( "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() );
myProcess->Close();
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 поток, можно управлять выводом ошибок процесса или подавлять их. Например, можно отфильтровать текст, отформатировать его по-разному или записать выходные данные как в консоль, так и в назначенный файл журнала.

Примечание

Чтобы использовать StandardError, необходимо задать значение ProcessStartInfo.UseShellExecutefalse, а — значение ProcessStartInfo.RedirectStandardErrortrue. В противном случае при чтении StandardError из потока возникает исключение.

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

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

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

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

Аналогичная проблема возникает при чтении всего текста как из стандартных выходных данных, так и из стандартных потоков ошибок. В следующем примере выполняется операция чтения в обоих потоках. Это позволяет избежать условия взаимоблокировки, выполняя асинхронные операции чтения в потоке StandardError . Условие взаимоблокировки возникает, если родительский процесс вызывает p.StandardOutput.ReadToEndp.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.

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

Примечание

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

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

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