Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ net.exe process and reads output from its stream reader.*/

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

namespace Process_StandardError
{
Expand Down Expand Up @@ -43,9 +42,8 @@ public static void GetStandardError(string[] args)
myProcess.StartInfo = myProcessStartInfo;
myProcess.Start();

StreamReader myStreamReader = myProcess.StandardError;
// Read the standard error of net.exe and write it on to console.
Console.WriteLine(myStreamReader.ReadLine());
Console.WriteLine(myProcess.StandardError.ReadLine());
}
// </Snippet1>
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Diagnostics;

class StandardOutputExample
Expand All @@ -14,8 +13,7 @@ public static void Main()
process.Start();

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

// Write the redirected output to this application's window.
Console.WriteLine(output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ myProcessStartInfo.RedirectStandardError <- true
myProcess.StartInfo <- myProcessStartInfo
myProcess.Start() |> ignore

let myStreamReader = myProcess.StandardError
// Read the standard error of net.exe and write it on to console.
printfn $"{myStreamReader.ReadLine()}"
printfn $"{myProcess.StandardError.ReadLine()}"
// </Snippet1>
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ proc.StartInfo.RedirectStandardOutput <- true
proc.Start() |> ignore

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

// Write the redirected output to this application's window.
printfn $"{output}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

Imports System.Diagnostics
Imports System.ComponentModel
Imports System.IO

Namespace Process_StandardError

Expand Down Expand Up @@ -37,9 +36,8 @@ Namespace Process_StandardError
myProcess.StartInfo = myProcessStartInfo
myProcess.Start()

Dim myStreamReader As StreamReader = myProcess.StandardError
' Read the standard error of net.exe and write it on to console.
Console.WriteLine(myStreamReader.ReadLine())
Console.WriteLine(myProcess.StandardError.ReadLine())
End Using
' </Snippet1>
End Sub
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Imports System.IO
Imports System.Diagnostics
Imports System.Diagnostics

Module Module1
Sub Main()
Expand All @@ -9,9 +8,8 @@ Module Module1
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()
' Synchronously read the standard output of the spawned process.
Dim output As String = process.StandardOutput.ReadToEnd()
Console.WriteLine(output)

process.WaitForExit()
Expand Down
9 changes: 9 additions & 0 deletions xml/System.Diagnostics/Process.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5085,6 +5085,9 @@ If no main module is found, it could be because the process hasn't finished load

The redirected <xref:System.Diagnostics.Process.StandardError*> stream can be read synchronously or asynchronously. Methods such as <xref:System.IO.StreamReader.Read*>, <xref:System.IO.StreamReader.ReadLine*>, and <xref:System.IO.StreamReader.ReadToEnd*> perform synchronous read operations on the error output stream of the process. These synchronous read operations do not complete until the associated <xref:System.Diagnostics.Process> writes to its <xref:System.Diagnostics.Process.StandardError*> stream, or closes the stream.

> [!IMPORTANT]
> When you read from the <xref:System.Diagnostics.Process.StandardError*> stream synchronously (for example, by calling <xref:System.IO.StreamReader.ReadToEnd*> or <xref:System.IO.StreamReader.ReadLine*>), the <xref:System.Diagnostics.Process> no longer disposes the stream when the process is disposed. In this case, you're responsible for disposing the <xref:System.IO.StreamReader> returned by <xref:System.Diagnostics.Process.StandardError*>, or you can call methods directly on the property (for example, `process.StandardError.ReadToEnd()`) within a `using` block for the <xref:System.Diagnostics.Process> instance. If you use <xref:System.Diagnostics.Process.BeginErrorReadLine*> to read the stream asynchronously, the <xref:System.Diagnostics.Process> retains ownership of the stream and disposes it when the process is disposed.

In contrast, <xref:System.Diagnostics.Process.BeginErrorReadLine*> starts asynchronous read operations on the <xref:System.Diagnostics.Process.StandardError*> stream. This method enables a designated event handler for the stream output and immediately returns to the caller, which can perform other work while the stream output is directed to the event handler.

Synchronous read operations introduce a dependency between the caller reading from the <xref:System.Diagnostics.Process.StandardError*> stream and the child process writing to that stream. These dependencies can result in deadlock conditions. When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits on the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits on the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait on each other to complete an operation, and neither can proceed. You can avoid deadlocks by evaluating dependencies between the caller and child process.
Expand Down Expand Up @@ -5181,6 +5184,9 @@ You can use asynchronous read operations to avoid these dependencies and their d
> [!NOTE]
> To use <xref:System.Diagnostics.Process.StandardInput*>, you must set <xref:System.Diagnostics.ProcessStartInfo.UseShellExecute*?displayProperty=nameWithType> to `false`, and you must set <xref:System.Diagnostics.ProcessStartInfo.RedirectStandardInput*?displayProperty=nameWithType> to `true`. Otherwise, writing to the <xref:System.Diagnostics.Process.StandardInput*> stream throws an exception.

> [!IMPORTANT]
> When you access the <xref:System.Diagnostics.Process.StandardInput*> stream, the <xref:System.Diagnostics.Process> no longer disposes the stream when the process is disposed. In this case, you're responsible for closing the <xref:System.IO.StreamWriter> by calling <xref:System.IO.StreamWriter.Close*>, or you can rely on disposing the <xref:System.Diagnostics.Process> within a `using` block and accessing <xref:System.Diagnostics.Process.StandardInput*> inline.



## Examples
Expand Down Expand Up @@ -5249,6 +5255,9 @@ You can use asynchronous read operations to avoid these dependencies and their d

The redirected <xref:System.Diagnostics.Process.StandardOutput*> stream can be read synchronously or asynchronously. Methods such as <xref:System.IO.StreamReader.Read*>, <xref:System.IO.StreamReader.ReadLine*>, and <xref:System.IO.StreamReader.ReadToEnd*> perform synchronous read operations on the output stream of the process. These synchronous read operations do not complete until the associated <xref:System.Diagnostics.Process> writes to its <xref:System.Diagnostics.Process.StandardOutput*> stream, or closes the stream.

> [!IMPORTANT]
> When you read from the <xref:System.Diagnostics.Process.StandardOutput*> stream synchronously (for example, by calling <xref:System.IO.StreamReader.ReadToEnd*> or <xref:System.IO.StreamReader.ReadLine*>), the <xref:System.Diagnostics.Process> no longer disposes the stream when the process is disposed. In this case, you're responsible for disposing the <xref:System.IO.StreamReader> returned by <xref:System.Diagnostics.Process.StandardOutput*>, or you can call methods directly on the property (for example, `process.StandardOutput.ReadToEnd()`) within a `using` block for the <xref:System.Diagnostics.Process> instance. If you use <xref:System.Diagnostics.Process.BeginOutputReadLine*> to read the stream asynchronously, the <xref:System.Diagnostics.Process> retains ownership of the stream and disposes it when the process is disposed.

In contrast, <xref:System.Diagnostics.Process.BeginOutputReadLine*> starts asynchronous read operations on the <xref:System.Diagnostics.Process.StandardOutput*> stream. This method enables a designated event handler for the stream output and immediately returns to the caller, which can perform other work while the stream output is directed to the event handler.

Synchronous read operations introduce a dependency between the caller reading from the <xref:System.Diagnostics.Process.StandardOutput*> stream and the child process writing to that stream. These dependencies can result in deadlock conditions. When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits on the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits on the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait on each other to complete an operation, and neither can proceed. You can avoid deadlocks by evaluating dependencies between the caller and child process.
Expand Down