- MSDN says ProcessStartInfo.UseShellExecute==True means use the shell when starting the process, does it mean that the process is started just the same as i run a cmd.exe and run the program from that command prompt? What's the point of doing this? Does the process started this way has its own console?
Actually it works like this:
- if UseShellExecute is false, the application will be started using the CreateProcess API; this API lets you specify a lot of startup options, among which there is the possibility to redirect stdin/stdout/stderr, but will only start executables. If you try to launch a file (e.g. a word document) with CreateProcess, it will fail, because word documents aren't executable files.
- if UseShellExecute is true, the process will be started using the ShellExecuteEx API; this function is the same function that Windows Explorer ("the shell", at least in Microsoft terminology) uses when you double click on a file in a folder; its main advantage is that it "knows" how to start documents (opening them with the associated programs), it's aware of shell folders, ... because it uses a lot of the shell facilities. However it has some major drawbacks: it's quite heavyweight compared to the bare CreateProcess (because it has to perform a lot of extra work), it fails to open even executables if something is wrong with file associations/shell extensions/... and it can't redirect stdin/stdout/stderr. Not that theoretically it would be impossible: after all ShellExecuteEx internally calls CreateProcess; the problem is that it doesn't expose this feature.
So, the two methods of creating a process are really quite different; the Process class does a great job at flattening them, but a feature that absolutely cannot be reproduced with the ShellExecuteEx function is the IO streams redirection, since it's not made available by the ShellExecuteEx function and it can be enabled only at process start via CreateProcess.
The use of the console by the started program is another question. The console is allocated/reused inside CreateProcess (actually IIRC it has to do with the windows PE loader, that checks the required subsystem in the PE header); the rules for console creation/reusing are specified here.
If the started application is a GUI application, no consoles are created at all; on the other hand, if a console application is started it reuses its parent process' console, unless it specified in the CreateProcess call the CREATE_NEW_CONSOLE flag. The default is not to specify this flag, but I'm not sure of what does ShellExecuteEx do with console applications, and I don't have a Windows box at hand to check. I'll leave this as an exercise to the reader. :P
Additional answers
Hi, Matteo, another question. If i create a new process as a detached process which don't have a console attached. Where is the process's stdout now? Where does's the process's output go? Is the process's stdout differnt from console's ouput?
It's not clear to me what you mean. When you start a new process with CreateProcess/ShellExecuteEx the console is allocated as needed, i.e. if the exe is a console executable (as specified in the PE header), Windows provides it a console (that is a new one or the parent's one depending on the rules I specified above); if the exe is a GUI application no console is allocated for it.
IIRC, for GUI applications stdout/stdin/stderr are just bit buckets, i.e. they point to nothing useful and all IO to them is discarded; by the way, nothing stops a GUI application from allocating a console and redirecting its own std* streams to it.
Keep in mind that the console, the Windows std streams and the CRT std streams are three separate things. The console is just an interface, that for console applications is conveniently bound by default to the Windows std streams.
The Windows std streams are the ones that are redirected when you specify stdin/stdout/stderr redirection in CreateProcess; you can get handles to them with the GetStdHandle function, and redirect them with the SetStdHandle.
The CRT stdin/stdout/stderr, finally, are yet another abstraction, built by the C runtime library; they are bound by default to the Windows std streams.
All this normally work seamlessly and you don't even have to bother about the difference between the Windows std streams and the CRT streams; however, when you start to think about streams redirection this difference becomes important.
If process's stdout stream is differnt from console's output, And Shell make the binding of these 2 streams for us. Would the ouput of a process be copied from process.stdout to console.output? is that efficient?
The shell isn't involved in this process, is the kernel that does the plumbing, following the instructions used in the CreateProcess (or subsequently modified from inside the new process with other APIs). For your performance concerns, with a layered structure like this it's the only way to go; and moreover, the copying part (if it's really a copy, I suspect that the whole thing is just a matter of passing pointers around) is the fastest part of the process, the real bottleneck is the console window painting/scrolling/etc. In facts, if you want to run a console application letting it produce data at full speed, you usually redirect its standard output to a file or through a pipe.
Many many thanks. Matteo Italia. You are a good problem sovler. :D
Thank you. :)