Process.StandardOutput 属性
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
获取用于读取应用程序文本输出的流。
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
属性值
StreamReader,可用于读取应用程序的标准输出流。
- 属性
例外
尚未对 StandardOutput 流进行重定向定义;请确保 RedirectStandardOutput 设置为 true
且 UseShellExecute 设置为 false
。
或
已打开 StandardOutput 流,以使用 BeginOutputReadLine() 进行异步读取操作。
示例
以下示例运行 ipconfig.exe 命令,并将其标准输出重定向到示例的控制台窗口。
using namespace System;
using namespace System::IO;
using namespace System::Diagnostics;
int main()
{
Process^ process = gcnew 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();
process->Close();
Console::WriteLine("\n\nPress any key to exit");
Console::ReadLine();
return 0;
}
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();
}
}
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
注解
当将 Process 文本写入其标准流时,该文本通常显示在主机上。 通过重定向 StandardOutput 流,可以操作或禁止显示进程的输出。 例如,可以筛选文本、设置不同的格式,或将输出写入控制台和指定的日志文件。
注意
若要使用 StandardOutput,必须将 设置为 ProcessStartInfo.UseShellExecutefalse
,并且必须设置为 ProcessStartInfo.RedirectStandardOutputtrue
。 否则,从流中 StandardOutput 读取会引发异常。
重定向的 StandardOutput 流可以同步或异步读取。 、 和 ReadToEnd 等ReadReadLine方法对进程的输出流执行同步读取操作。 这些同步读取操作在关联 Process 写入其 StandardOutput 流或关闭流之前不会完成。
相比之下,对 BeginOutputReadLineStandardOutput 流启动异步读取操作。 此方法为流输出启用指定的事件处理程序,并立即返回到调用方,后者可以在流输出定向到事件处理程序时执行其他工作。
同步读取操作在从流读取的调用方与写入该 StandardOutput 流的子进程之间引入了依赖关系。 这些依赖项可能会导致死锁情况。 当调用方从子进程的重定向流中读取时,它依赖于子进程。 调用方等待读取操作,直到子写入流或关闭流。 当子进程写入足够的数据来填充其重定向流时,它依赖于父进程。 子进程等待下一个写入操作,直到父进程从完整流读取或关闭流。 当调用方和子进程相互等待完成操作并且两者都无法继续时,会导致死锁情况。 可以通过评估调用方和子进程之间的依赖关系来避免死锁。
本节中的最后两个示例使用 Start 方法启动名为 Write500Lines.exe的可执行文件。 以下示例包含其源代码。
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.
以下示例演示如何从重定向的流中读取并等待子进程退出。 该示例通过在 之前p.WaitForExit
调用 p.StandardOutput.ReadToEnd
来避免死锁条件。 如果父进程先调用 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:
// ' 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%
' '
从标准输出流和标准错误流读取所有文本时,也会出现类似的问题。 以下示例对两个流执行读取操作。 它通过在流上 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:
// ' 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.
可以使用异步读取操作来避免这些依赖项及其死锁的可能性。 或者,可以通过在单独的线程上创建两个线程并读取每个流的输出来避免死锁情况。
注意
不能在重定向流上混合执行异步读取操作和同步读取操作。 在异步或同步模式下打开 的重定向流 Process 后,该流上的所有进一步读取操作都必须处于同一模式。 例如,不要在流上执行 BeginOutputReadLine 对 ReadLine 的 StandardOutput 调用,反之亦然。 但是,可以在不同的模式下读取两个不同的流。 例如,可以调用 BeginOutputReadLine 流,然后调用 ReadLine 流 StandardError 。