December 5th, 2025
mind blown1 reaction

How can my process read its own standard output?

A customer wanted to know how their C# program could read its own standard output. They tried this:

// Get my process
Process p = Process.GetCurrentProcess();

// Make sure my standard output is not redirected
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = false;

// Now read it -- fails
string output = p.StandardOutput.ReadToEnd();

They got an exception saying, “StandardOut has not been redirected or the process hasn’t started yet.”

The Standard­Output property is valid only after you call Process.Start. Specifically, if you call Process.Start when Redirect­Standard­Output is set to true the CLR creates a pipe and connects the write end of the pipe to the child’s standard output and the read end of the pipe to the Process.Standard­Output property. If you never call Process.Start, or you did not enable standard output redirection, then the Process.Standard­Output property will not be set and will not work.

In my opinion, putting properties on the Process object that are meaningful only for started processes was a mistake. Those properties should have been put on a new class like Process­Start­Result. That way, it’s clear that the only way to get them is to start a process.

If you are a C# process, you could call Console.SetOut() to replace the standard output with a pipe you created.¹ However, if anybody read the Console.Out property and saved it in a variable, then they would still be operating on the original standard output stream and not your replacement.

The most reliable solution is to relaunch yourself as a child process with redirected standard output and have the parent read from the resulting Process.StandardOutput stream while the child writes to it.

¹ This is the CLR analog to the Win32 function Set­Std­Handle(). Note that Win32 and the CLR have separate bookkeeping for this. The CLR initializes its standard output from the Win32 standard output, but the two can diverge afterward because the CLR does not bother to keep its value in sync with Win32 or vice versa.

Note also that the analogy continues, because the analogous solution for Win32 console programs is to call Set­Std­Handle, but you have the same risk that somebody has already read the original standard handle and saved it away. And as we saw last time, that risk is a reality because the C runtime library does exactly that. The analogous functions to Console.SetOut() for C are those in the freopen family.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Sort by :
  • Igor Levicki · Edited

    Raymond, my condolences.

    If someone asked me that question, I’d probably be less patient.

    Maybe I am misunderstanding, but…

    WHY would you want to read your OWN standard output?

    I mean, aren’t YOU the one producing said output? If so, then why not just copy the string you just Console.WriteLine’d?!?

    Trying to read your own STDOUT is like writing a note to yourself, throwing it out the window, then running down 30 flights of stairs to catch it and read it again.

    I swear, people are dumb as rocks today.

    • Bwmat

      Yeah, I was about to ask something similar; I don’t think it’s _possible_ to read from your own process’ stderr since that’s (usually?) a write-only pipe/file/whatever?

  • GL 3 hours ago

    Setting StartInfo.UseShellExecute for the current process is pretty humorous because that would imply one can change how a process *was* started after it has started.