ProcessStartInfo.RedirectStandardOutput Propriedade
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Obtém ou define um valor que indica se a saída textual de um aplicativo é gravada no fluxo 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
Valor da propriedade
true
se a saída deve ser gravada StandardOutput; caso contrário, false
. O padrão é false
.
Exemplos
// 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
Comentários
Quando um Process grava texto em seu fluxo padrão, esse texto normalmente é exibido no console. Ao definir RedirectStandardOutput como true
para redirecionar o StandardOutput fluxo, você pode manipular ou suprimir a saída de um processo. Por exemplo, você pode filtrar o texto, formatá-lo de forma diferente ou gravar a saída no console e em um arquivo de log designado.
Observação
Você deve definir UseShellExecute como false
se quiser definir RedirectStandardOutput como true
. Caso contrário, a leitura do StandardOutput fluxo gerará uma exceção.
O fluxo redirecionado StandardOutput pode ser lido de forma síncrona ou assíncrona. Métodos como Read, ReadLinee ReadToEnd executam operações de leitura síncronas no fluxo de saída do processo. Essas operações de leitura síncronas não são concluídas até que o associado Process grave em seu StandardOutput fluxo ou feche o fluxo.
Por outro lado, BeginOutputReadLine inicia operações de leitura assíncronas no StandardOutput fluxo. Esse método habilita um manipulador de eventos designado (consulte OutputDataReceived) para a saída do fluxo e retorna imediatamente ao chamador, que pode executar outro trabalho enquanto a saída do fluxo é direcionada para o manipulador de eventos.
Observação
O aplicativo que está processando a saída assíncrona deve chamar o WaitForExit método para garantir que o buffer de saída tenha sido liberado.
As operações de leitura síncronas introduzem uma dependência entre a leitura do chamador do StandardOutput fluxo e o processo filho que está gravando nesse fluxo. Essas dependências podem causar condições de deadlock. Quando o chamador lê do fluxo redirecionado de um processo filho, ele depende do filho. O chamador aguarda a operação de leitura até que o filho grave no fluxo ou feche o fluxo. Quando o processo filho grava dados suficientes para preencher seu fluxo redirecionado, ele depende do pai. O processo filho aguarda a próxima operação de gravação até que o pai leia do fluxo completo ou feche o fluxo. A condição de deadlock resulta quando o chamador e o processo filho esperam que um ao outro conclua uma operação e nenhum deles pode continuar. Você pode evitar deadlocks avaliando dependências entre o processo de chamador e filho.
Os dois últimos exemplos nesta seção usam o Start método para iniciar um executável chamado Write500Lines.exe. O exemplo a seguir contém seu código-fonte.
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.
O exemplo a seguir mostra como ler de um fluxo redirecionado e aguardar a saída do processo filho. O exemplo evita uma condição de deadlock chamando p.StandardOutput.ReadToEnd
antes p.WaitForExit
de . Uma condição de deadlock poderá resultar se o processo pai chamar p.WaitForExit
antes p.StandardOutput.ReadToEnd
e o processo filho gravar texto suficiente para preencher o fluxo redirecionado. O processo pai aguardaria indefinidamente a saída do processo filho. O processo filho aguardaria indefinidamente para que o pai lesse o fluxo 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:
// ' 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%
' '
Há um problema semelhante quando você lê todo o texto dos fluxos de erro padrão e de saída padrão. O exemplo a seguir executa uma operação de leitura em ambos os fluxos. Ele evita a condição de deadlock executando operações de leitura assíncronas no StandardError fluxo. Uma condição de deadlock resultará se o processo pai chamar p.StandardOutput.ReadToEnd
seguido por p.StandardError.ReadToEnd
e o processo filho gravar texto suficiente para preencher seu fluxo de erros. O processo pai aguardaria indefinidamente para que o processo filho fechasse seu StandardOutput fluxo. O processo filho aguardaria indefinidamente para que o pai lesse o fluxo 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:
// ' 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.
Você pode usar operações de leitura assíncronas para evitar essas dependências e seu potencial de deadlock. Como alternativa, você pode evitar a condição de deadlock criando dois threads e lendo a saída de cada fluxo em um thread separado.