Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Since it works correctly when the parent process is a console application, why not just temporarily turn it into one?</p> <pre><code>[DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool AllocConsole(); [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool FreeConsole(); private static void Main(string[] args) { Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardError = false; p.StartInfo.FileName = "Child.exe"; p.StartInfo.Arguments = "i"; AllocConsole(); p.Start(); FreeConsole(); string processOutput = p.StandardOutput.ReadToEnd(); p.WaitForExit(); Debug.WriteLine("The child process output is:" + processOutput); } </code></pre> <p>If you use a <code>lock</code> around <code>AllocConsole</code>/<code>Start</code>/<code>FreeConsole</code>, you can even start up multiple child processes, each with its own console window.</p> <hr> <p>This is an older 'solution' that did not work properly.</p> <p>Take a look at the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx" rel="nofollow">CreateProcess flags</a>. Not setting CREATE_NO_WINDOW doesn't give you a new console object; you need CREATE_NEW_CONSOLE. [nope, this was wrong; see below]</p> <p>Unfortunately, that isn't exposed in the .NET API. <code>Process.Start</code> does the right thing if you let it use <code>ShellExecute</code>, but then you can't redirect stdout. I think what you are trying to do is impossible with <code>System.Diagnostics.Process</code>, you will have to P/Invoke <code>CreateProcess</code>.</p> <p>Just yesterday I wrote my own <code>System.Diagnostics.Process</code> alternative because I needed another feature not provided by the MS implementation - redirect both stdout and stderr to the same stream. Feel free to reuse <a href="https://gist.github.com/dgrunwald/5331022" rel="nofollow">my code</a>, but keep in mind it didn't get much testing yet.</p> <p>I've tested your example with my <code>ProcessRunner</code>, and it works as expected if the parent process is a console application - the child gets its own new console window (not reusing the one from the parent as <code>System.Diagnostics.Process</code> does), it can <code>ReadKey()</code> from it, and stdout is redirected to the parent.</p> <p>But if the parent process is a windows application, this breaks down -- <code>ReadKey()</code> fails; and <code>stderr</code> output also isn't visible. (this is exactly the same behavior as <code>System.Diagnostics.Process</code>, I just didn't realize that <code>stderr</code> also wasn't working. The reason for this is that you can't just redirect one of the streams - as soon as <code>STARTF_USESTDHANDLES</code> is set, all the streams are redirected.</p> <p>Now I'm not sure why it works if the parent application is a console. Maybe the redirected stdin/stderr handles refer to the current console, not the console that was current when <code>GetStdHandle</code> was called.</p> <p>But if <code>GetStdHandle</code> is called within a Windows application, it returns INVALID_HANDLE. I'm not sure if there's a way to get a handle that will be valid once a console is created. Answer: do don't that, just create the console earlier (see new solution at beginning).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload