Process.StandardError Właściwość

Definicja

Pobiera strumień używany do odczytywania danych wyjściowych błędu aplikacji.

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

Wartość właściwości

Element StreamReader , który może służyć do odczytywania standardowego strumienia błędów aplikacji.

Atrybuty

Wyjątki

Strumień StandardError nie został zdefiniowany na potrzeby przekierowania; upewnij się RedirectStandardError , że ustawiono true wartość i UseShellExecute ustawiono wartość false.

— lub —

Strumień StandardError został otwarty dla operacji odczytu asynchronicznego za pomocą polecenia BeginErrorReadLine().

Przykłady

W poniższym przykładzie użyto net use polecenia razem z podanym przez użytkownika argumentem, aby zamapować zasób sieciowy. Następnie odczytuje standardowy strumień błędów polecenia net i zapisuje go w konsoli.

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());
}
use myProcess = new Process()
let myProcessStartInfo = ProcessStartInfo("net ", $"use {args[0]}")

myProcessStartInfo.UseShellExecute <- false
myProcessStartInfo.RedirectStandardError <- true
myProcess.StartInfo <- myProcessStartInfo
myProcess.Start() |> ignore

let myStreamReader = myProcess.StandardError
// Read the standard error of net.exe and write it on to console.
printfn $"{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

Uwagi

Process Gdy tekst jest zapisywany w standardowym strumieniu błędów, tekst jest zwykle wyświetlany w konsoli programu . Przekierowując StandardError strumień, można manipulować lub pomijać dane wyjściowe błędu procesu. Można na przykład filtrować tekst, formatować go inaczej lub zapisywać dane wyjściowe zarówno w konsoli, jak i wyznaczonym pliku dziennika.

Note

Aby użyć StandardErrorelementu , musisz ustawić wartość ProcessStartInfo.UseShellExecutefalse, a musisz ustawić wartość ProcessStartInfo.RedirectStandardErrortrue. W przeciwnym razie odczyt ze strumienia StandardError zgłasza wyjątek.

Przekierowany StandardError strumień można odczytywać synchronicznie lub asynchronicznie. Metody takie jak Read, ReadLinei ReadToEnd wykonują synchroniczne operacje odczytu na strumieniu danych wyjściowych błędu procesu. Te synchroniczne operacje odczytu nie są wykonywane, dopóki skojarzone z nim ProcessStandardError operacje zapisu nie zakończą się ani nie zamykają strumienia.

BeginErrorReadLine Natomiast uruchamia operacje asynchronicznego odczytu w strumieniuStandardError. Ta metoda umożliwia wyznaczoną procedurę obsługi zdarzeń dla danych wyjściowych strumienia i natychmiast wraca do elementu wywołującego, co może wykonać inną pracę, gdy dane wyjściowe strumienia są kierowane do programu obsługi zdarzeń.

Synchroniczne operacje odczytu wprowadzają zależność między odczytem obiektu wywołującego ze strumienia StandardError a procesem podrzędnym zapisu w tym strumieniu. Te zależności mogą spowodować zakleszczenie warunków. Gdy obiekt wywołujący odczytuje z przekierowanego strumienia procesu podrzędnego, jest zależny od elementu podrzędnego. Obiekt wywołujący czeka na operację odczytu, dopóki element podrzędny nie zapisze strumienia lub zamknie strumień. Gdy proces podrzędny zapisuje wystarczającą ilość danych, aby wypełnić przekierowany strumień, jest zależny od elementu nadrzędnego. Proces podrzędny czeka na następną operację zapisu, dopóki element nadrzędny nie odczytuje z pełnego strumienia lub zamknie strumień. Warunek zakleszczenia powoduje, że wywołanie i proces podrzędny czekają na siebie nawzajem, aby ukończyć operację, i nie mogą kontynuować. Można uniknąć zakleszczeń, oceniając zależności między obiektem wywołującym a procesem podrzędnym.

W dwóch ostatnich przykładach w tej sekcji użyto Start metody , aby uruchomić plik wykonywalny o nazwie Write500Lines.exe. Poniższy przykład zawiera kod źródłowy.

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.
module Write500Lines

for i in 1. .. 500. do
    printfn $"Line {i} of 500 written: {i/500.:P2}";

eprintfn "Successfully wrote 500 lines.";
// 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.

W poniższym przykładzie pokazano, jak odczytywać ze strumienia błędu przekierowanego i czekać na zakończenie procesu podrzędnego. Zapobiega to zakleszczeniom przez wywołanie p.StandardError.ReadToEnd metody przed p.WaitForExit. Warunek zakleszczenia może spowodować wywołanie procesu p.WaitForExit nadrzędnego przed i p.StandardError.ReadToEnd proces podrzędny zapisuje wystarczająco dużo tekstu, aby wypełnić przekierowany strumień. Proces nadrzędny będzie czekał na zakończenie procesu podrzędnego przez czas nieokreślony. Proces podrzędny będzie czekał na czas nieokreślony, aż element nadrzędny będzie odczytywał z pełnego StandardError strumienia.

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.
module STDErrorSync

open System.Diagnostics

let p = new Process()
p.StartInfo.UseShellExecute <- false
p.StartInfo.RedirectStandardError <- true
p.StartInfo.FileName <- "Write500Lines.exe"
p.Start() |> ignore

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

printfn $"\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.

Podobny problem występuje podczas odczytywania całego tekstu zarówno ze standardowych strumieni danych wyjściowych, jak i standardowych błędów. Poniższy przykład wykonuje operację odczytu na obu strumieniach. Pozwala uniknąć zakleszczenia, wykonując asynchroniczne operacje odczytu w strumieniu StandardError . Warunek zakleszczenia powoduje, że wywołania p.StandardOutput.ReadToEnd procesu nadrzędnego, a p.StandardError.ReadToEnd proces podrzędny zapisuje wystarczającą ilość tekstu, aby wypełnić strumień błędu. Proces nadrzędny czekałby na czas nieokreślony, aż proces podrzędny zamknie strumień StandardOutput . Proces podrzędny będzie czekał na czas nieokreślony, aż element nadrzędny będzie odczytywał z pełnego StandardError strumienia.

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.
module STDOutputAsync

open System.Diagnostics

let p = new Process()
p.StartInfo.UseShellExecute <- false
p.StartInfo.RedirectStandardOutput <- true
let mutable eOut = ""
p.StartInfo.RedirectStandardError <- true
p.ErrorDataReceived.AddHandler(DataReceivedEventHandler(fun sender e -> eOut <- eOut + e.Data))

p.StartInfo.FileName <- "Write500Lines.exe"
p.Start() |> ignore

// To avoid deadlocks, use an asynchronous read operation on at least one of the streams.
p.BeginErrorReadLine()
let output = p.StandardOutput.ReadToEnd()
p.WaitForExit()

printfn $"The last 50 characters in the output stream are:\n'{output.Substring(output.Length - 50)}'"
printfn $"\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.

Możesz użyć operacji odczytu asynchronicznego, aby uniknąć tych zależności i ich potencjału zakleszczenia. Alternatywnie można uniknąć stanu zakleszczenia, tworząc dwa wątki i odczytując dane wyjściowe każdego strumienia w osobnym wątku.

Note

Nie można mieszać asynchronicznych i synchronicznych operacji odczytu na przekierowanym strumieniu. Po otwarciu przekierowanego strumienia elementu Process w trybie asynchronicznym lub synchronicznym wszystkie dalsze operacje odczytu na tym strumieniu muszą być w tym samym trybie. Na przykład nie należy wykonywać wywołania BeginErrorReadLine metody ReadLine w strumieniu StandardError lub odwrotnie. Można jednak odczytywać dwa różne strumienie w różnych trybach. Możesz na przykład wywołać BeginOutputReadLine metodę StandardError , a następnie wywołać ReadLine strumień.

Dotyczy

Zobacz też