Process.StandardOutput Proprietà

Definizione

Ottiene un flusso utilizzato per leggere l'output testuale dell'applicazione.

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

Valore della proprietà

Oggetto StreamReader che può essere usato per leggere il flusso di output standard dell'applicazione.

Attributi

Eccezioni

Il StandardOutput flusso non è stato definito per il reindirizzamento. Assicurarsi che RedirectStandardOutput sia impostato su true e UseShellExecute sia impostato su false.

oppure

Il StandardOutput flusso è stato aperto per le operazioni di lettura asincrone con BeginOutputReadLine().

Esempio

L'esempio seguente esegue il comando ipconfig.exe e reindirizza l'output standard alla finestra della console dell'esempio.

using System;
using System.IO;
using System.Diagnostics;

class StandardOutputExample
{
    public static void Main()
    {
        using (Process process = new Process())
        {
            process.StartInfo.FileName = "ipconfig.exe";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();

            // Synchronously read the standard output of the spawned process.
            StreamReader reader = process.StandardOutput;
            string output = reader.ReadToEnd();

            // Write the redirected output to this application's window.
            Console.WriteLine(output);

            process.WaitForExit();
        }

        Console.WriteLine("\n\nPress any key to exit.");
        Console.ReadLine();
    }
}
module ProcessStandardOutput

open System.Diagnostics

use proc = new Process()
proc.StartInfo.FileName <- "ipconfig.exe"
proc.StartInfo.UseShellExecute <- false
proc.StartInfo.RedirectStandardOutput <- true
proc.Start() |> ignore

// Synchronously read the standard output of the spawned process.
let reader = proc.StandardOutput
let output = reader.ReadToEnd()

// Write the redirected output to this application's window.
printfn $"{output}"

proc.WaitForExit()

printfn "\n\nPress any key to exit."
stdin.ReadLine() |> ignore
Imports System.IO
Imports System.Diagnostics

Module Module1
    Sub Main()
        Using process As New Process()
            process.StartInfo.FileName = "ipconfig.exe"
            process.StartInfo.UseShellExecute = False
            process.StartInfo.RedirectStandardOutput = True
            process.Start()

            ' Synchronously read the standard output of the spawned process. 
            Dim reader As StreamReader = process.StandardOutput
            Dim output As String = reader.ReadToEnd()
            Console.WriteLine(output)

            process.WaitForExit()
        End Using

        Console.WriteLine(Environment.NewLine + Environment.NewLine + "Press any key to exit.")
        Console.ReadLine()
    End Sub
End Module

Commenti

Quando un oggetto Process scrive testo nel flusso standard, tale testo viene in genere visualizzato nella console. Reindirizzando il StandardOutput flusso, è possibile modificare o eliminare l'output di un processo. Ad esempio, è possibile filtrare il testo, formattarlo in modo diverso o scrivere l'output sia nella console che in un file di log designato.

Note

Per usare StandardOutput, è necessario impostare su ProcessStartInfo.UseShellExecutefalse e è necessario impostare su ProcessStartInfo.RedirectStandardOutputtrue. In caso contrario, la lettura dal StandardOutput flusso genera un'eccezione.

Il flusso reindirizzato StandardOutput può essere letto in modo sincrono o asincrono. Metodi come Read, ReadLineed eseguono ReadToEnd operazioni di lettura sincrone sul flusso di output del processo. Queste operazioni di lettura sincrone non vengono completate fino a quando le scritture associate nel Process flusso StandardOutput non vengono completate o chiude il flusso.

Al contrario, BeginOutputReadLine avvia operazioni di lettura asincrone nel StandardOutput flusso. Questo metodo abilita un gestore eventi designato per l'output del flusso e torna immediatamente al chiamante, che può eseguire altre operazioni mentre l'output del flusso viene indirizzato al gestore eventi.

Le operazioni di lettura sincrone introducono una dipendenza tra la lettura del StandardOutput chiamante dal flusso e il processo figlio che scrive in tale flusso. Queste dipendenze possono causare condizioni di deadlock. Quando il chiamante legge dal flusso reindirizzato di un processo figlio, dipende dall'elemento figlio. Il chiamante attende l'operazione di lettura fino a quando l'elemento figlio non scrive nel flusso o chiude il flusso. Quando il processo figlio scrive dati sufficienti per riempire il flusso reindirizzato, dipende dall'elemento padre. Il processo figlio attende l'operazione di scrittura successiva finché l'elemento padre non legge dal flusso completo o chiude il flusso. La condizione di deadlock restituisce quando il chiamante e il processo figlio attendono l'uno dall'altro per completare un'operazione e nessuno dei due può continuare. È possibile evitare deadlock valutando le dipendenze tra il chiamante e il processo figlio.

Gli ultimi due esempi in questa sezione usano il Start metodo per avviare un eseguibile denominato Write500Lines.exe. L'esempio seguente contiene il codice sorgente.

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.

Nell'esempio seguente viene illustrato come leggere da un flusso reindirizzato e attendere l'uscita del processo figlio. Nell'esempio viene evitata una condizione di deadlock chiamando p.StandardOutput.ReadToEnd prima p.WaitForExitdi . Una condizione di deadlock può determinare se il processo padre chiama p.WaitForExit prima p.StandardOutput.ReadToEnd e il processo figlio scrive testo sufficiente per riempire il flusso reindirizzato. Il processo padre attenderà a tempo indeterminato l'uscita del processo figlio. Il processo figlio attende a tempo indeterminato che l'elemento padre legga dal flusso completo StandardOutput .

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:
//      'ritten: 99,80%
//      Line 500 of 500 written: 100,00%
//      '
module STDOutputSync

open System.Diagnostics

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

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

printfn $"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:
//      'ritten: 99,80%
//      Line 500 of 500 written: 100,00%
//      '
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:
'      'ritten: 99,80%
'      Line 500 of 500 written: 100,00%
'      '

Si verifica un problema simile quando si legge tutto il testo sia dall'output standard che dai flussi di errore standard. Nell'esempio seguente viene eseguita un'operazione di lettura su entrambi i flussi. Evita la condizione di deadlock eseguendo operazioni di lettura asincrone nel StandardError flusso. Una condizione di deadlock restituisce se il processo padre chiama p.StandardOutput.ReadToEnd seguito da p.StandardError.ReadToEnd e il processo figlio scrive testo sufficiente per riempire il flusso di errore. Il processo padre attende a tempo indeterminato che il processo figlio chiuda il flusso StandardOutput . Il processo figlio attende a tempo indeterminato che l'elemento padre legga dal flusso completo 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.
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.

È possibile usare operazioni di lettura asincrone per evitare queste dipendenze e il potenziale di deadlock. In alternativa, è possibile evitare la condizione di deadlock creando due thread e leggendo l'output di ogni flusso in un thread separato.

Note

Non è possibile combinare operazioni di lettura asincrone e sincrone in un flusso reindirizzato. Una volta aperto il flusso reindirizzato di un oggetto Process in modalità asincrona o sincrona, tutte le operazioni di lettura aggiuntive su tale flusso devono trovarsi nella stessa modalità. Ad esempio, non seguire BeginOutputReadLine con una chiamata a ReadLine sul StandardOutput flusso o viceversa. Tuttavia, è possibile leggere due flussi diversi in modalità diverse. Ad esempio, è possibile chiamare e quindi chiamare BeginOutputReadLineReadLine per il StandardError flusso.

Si applica a

Vedi anche