ProcessStartInfo.RedirectStandardOutput Właściwość

Definicja

Pobiera lub ustawia wartość wskazującą, czy tekstowe dane wyjściowe aplikacji są zapisywane w strumieniu 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

Wartość właściwości

truejeśli dane wyjściowe powinny być zapisywane w ; StandardOutputw przeciwnym razie . false Wartość domyślna to false.

Przykłady

// 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

Uwagi

Process Gdy tekst jest zapisywany w standardowym strumieniu, tekst jest zwykle wyświetlany w konsoli programu . Ustawiając wartość RedirectStandardOutput na , aby true przekierować StandardOutput strumień, można manipulować lub pomijać dane wyjściowe procesu. Można na przykład filtrować tekst, formatować go inaczej lub zapisywać dane wyjściowe zarówno w konsoli, jak i w wyznaczonym pliku dziennika.

Uwaga

Należy ustawić wartość na , jeśli chcesz ustawić wartość RedirectStandardOutputtrue.UseShellExecutefalse W przeciwnym razie odczyt ze strumienia StandardOutput zgłasza wyjątek.

Przekierowany StandardOutput strumień można odczytywać synchronicznie lub asynchronicznie. Metody takie jak Read, ReadLinei ReadToEnd wykonują synchroniczne operacje odczytu na strumieniu wyjściowym procesu. Te synchroniczne operacje odczytu nie są wykonywane, dopóki skojarzony z nim ProcessStandardOutput zapis nie zostanie zamknięty lub nie zamknie strumienia.

Z kolei BeginOutputReadLine operacje odczytu asynchronicznego są uruchamiane w strumieniu StandardOutput . Ta metoda umożliwia wyznaczoną procedurę obsługi zdarzeń (zobacz OutputDataReceived) 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ń.

Uwaga

Aplikacja, która przetwarza dane wyjściowe asynchroniczne, powinna wywołać metodę WaitForExit , aby upewnić się, że bufor wyjściowy został opróżniony.

Synchroniczne operacje odczytu wprowadzają zależność między odczytywaniem elementu wywołującego ze strumienia StandardOutput a procesem podrzędnym zapisu w tym strumieniu. Te zależności mogą powodować warunki zakleszczenia. Gdy obiekt wywołujący odczytuje z przekierowanego strumienia procesu podrzędnego, jest on zależny od elementu podrzędnego. Obiekt wywołujący czeka na operację odczytu do momentu zapisania podrzędnego do strumienia lub zamknięcia strumienia. 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 jest wynikiem, gdy wywołujący i podrzędny proces czekają na siebie nawzajem, aby ukończyć operację, i nie można 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;
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.

W poniższym przykładzie pokazano, jak odczytywać z przekierowanego strumienia i czekać na zakończenie procesu podrzędnego. W tym przykładzie nie ma warunku zakleszczenia przez wywołanie p.StandardOutput.ReadToEnd metody przed p.WaitForExit. Warunek zakleszczenia może spowodować wywołanie p.WaitForExit procesu nadrzędnego przed i p.StandardOutput.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 czekałby na czas nieokreślony, aż element nadrzędny będzie odczytywał z pełnego StandardOutput strumienia.

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%
'      '

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ąć warunku zakleszczenia, wykonując asynchroniczne operacje odczytu w strumieniu StandardError . Warunek zakleszczenia jest wynikiem wywołań p.StandardOutput.ReadToEnd procesu nadrzędnego, po którym następuje p.StandardError.ReadToEnd proces podrzędny, a proces podrzędny zapisuje wystarczająco dużo tekstu, aby wypełnić strumień błędu. Proces nadrzędny będzie czekać na czas nieokreślony, aż proces podrzędny zamknie strumień StandardOutput . Proces podrzędny czekałby 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:
//      ' 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.

Możesz użyć asynchronicznych operacji odczytu, 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.

Dotyczy

Zobacz też