ProcessStartInfo.RedirectStandardOutput 属性
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
获取或设置一个值,该值指示应用程序的文本输出是否写入 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
属性值
true 如果输出应写入到 StandardOutput,则为 ;否则为 false。 默认值为 false。
示例
// 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
注解
Process当文本写入其标准流时,该文本通常显示在主机上。 通过设置为RedirectStandardOutputtrue重定向StandardOutput流,可以操作或取消进程的输出。 例如,可以筛选文本、以不同的方式设置格式,或将输出写入控制台和指定的日志文件。
注释
如果要设置为 .,则必须UseShellExecutefalse设置为 RedirectStandardOutput。true 否则,从 StandardOutput 流中读取将引发异常。
StandardOutput重定向的流可以同步或异步读取。 方法,例如 Read, ReadLine对 ReadToEnd 进程的输出流执行同步读取操作。 在关联 Process 写入流 StandardOutput 或关闭流之前,这些同步读取操作不会完成。
相比之下, BeginOutputReadLine 在流上 StandardOutput 启动异步读取操作。 此方法为流输出启用指定的事件处理程序(请参阅 OutputDataReceived),并立即返回到调用方,该调用方可以在流输出定向到事件处理程序时执行其他工作。
注释
正在处理异步输出的应用程序应调用 WaitForExit 该方法,以确保已刷新输出缓冲区。
同步读取操作引入了从 StandardOutput 流读取的调用方与写入该流的子进程之间的依赖关系。 这些依赖项可能会导致死锁条件。 当调用方从子进程的重定向流中读取时,它依赖于子进程。 调用方等待读取操作,直到子写入流或关闭流。 当子进程写入足够的数据来填充其重定向流时,它依赖于父级。 子进程等待下一个写入操作,直到父级从完整流中读取或关闭流。 死锁条件在调用方和子进程等待对方完成操作时产生,并且两者都无法继续。 可以通过评估调用方和子进程之间的依赖关系来避免死锁。
本节中的最后两个示例使用 Start 该方法启动名为 Write500Lines.exe的可执行文件。 以下示例包含其源代码。
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.
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.
以下示例演示如何从重定向流中读取并等待子进程退出。 该示例通过调用之前p.StandardOutput.ReadToEnd调用p.WaitForExit来避免死锁条件。 如果父进程之前p.WaitForExit调用p.StandardOutput.ReadToEnd并且子进程写入足够的文本来填充重定向流,则死锁条件可能会造成。 父进程将无限期等待子进程退出。 子进程将无限期等待父级从完整 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%
// '
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%
' '
从标准输出和标准错误流读取所有文本时,会出现类似的问题。 以下示例对两个流执行读取操作。 它通过对 StandardError 流执行异步读取操作来避免死锁条件。 如果父进程调用 p.StandardOutput.ReadToEnd 后跟 p.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:
// '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.
可以使用异步读取操作来避免这些依赖项及其死锁潜力。 或者,可以通过创建两个线程并在单独的线程上读取每个流的输出来避免死锁条件。