How to start a console app in a new window, the parent's window, or no window

The ProcessStartInfo.CreateNoWindow property says "Gets or sets a value indicating whether to start the process in a new window." and later "true to start the process without creating a new window to contain it; otherwise, false. The default is false
But that's misleading and wrong because it's meaning changes depending on what another property (UseShellExecute) is. 

This caused me quite a bit of grief. So in the interests of helping you avoid my pain, here's what I found: (I originally started typing the feedback via MSDN Wiki; but it got long enough that I figure I may as well put it on my blog too.)

1) To run the child process without any window,

use the CreateNoWindow property and set UseShellExecute.

ProcessStartInfo info = new ProcessStartInfo(fileName, arg);
info.CreateNoWindow = true;
info.UseShellExecute = false;
Process processChild = Process.Start(info);
 

UseShellExecute=false means that Process.Start basically becomes a direct call to kernel32!CreateProcess. Practically, this means that now you just need to figure out how various ProcessStartInfo properties map to kernel32!CreateProcess flags. Presumably ProcessStartInfo defaults most flags to 0. The CreateNoWindow property translates to a CREATE_NO_WINDOW flag being passed to kernel32!CreateProcess, which means the console app runs without a window at all.  The default is to share console windows and you need to pass the CREATE_NEW_CONSOLE flag to give the child a new console.

2) To run the child process in it's own window (a new console window separate from the parent):

UseShellExecute=true, which is the default value.
ProcessStartInfo info = new ProcessStartInfo(fileName, arg);
Process processChild = Process.Start(info); // separate window

3) To run the child process in the parent's console window:

UseShellExecute=false.
ProcessStartInfo info = new ProcessStartInfo(fileName, arg);
info.UseShellExecute = false; // causes consoles to share window
Process processChild = Process.Start(info);
 

Or in nice table summary:

UseShellExecute CreateNoWindow Child console process runs in MSDN is
false true no window correct
true (default) false (default) a new window wrong
false false (default) an existing window (its parents') correct

 

Some design lessons:
There are some design lessons here:
1. Be precise in definitions when documenting your properties.  There's a significant difference between "a new window", "an existing window", and "no window".
2. Don't have a property's meaning completely change when some other unrelated property is set.

 

See also: Conventions for passing arguments to a process