I’ll start off by saying that there is not much use for this because ordinarily you would use the .NET Framework’s built in Process class, but there are some rare scenarios where that is not possible so hopefully this will help some of you in that situation out. Basically this is a small vb.net app that demonstrates how to redirect the input and output of a console application that you have launched via the CreateProcess API (or CreateProcessAsUser etc).
This was a real nightmare to get working but I’ve finally got it to a usable state, so if you want to give the demo app a try and look at the source code (which I have added loads of comments to) then here it is (screenshot and full source code included): http://www.vbforums.com/showthread.php?p=3821573
It uses the following Windows APIs: CreatePipe, DuplicateHandle, CloseHandle, CreateProcess, WaitForMultipleObjects, PeekNamedPipe, ReadFile and WriteFile
and here is a simplified explanation of how it works:
- Uses CreatePipe to create two anonymous pipes (one for input and one for output/error) and keeps a reference to the handles for writing to each end of these pipes
- The “write end” handle for the input pipe and the “read end” handle for the output pipe are kept to be used by our app but they are duplicated and marked as non inheritable so that when we start the child process it does not inherit these handles
- Create a START_INFO structure that specifies parameters for the process we are going to launch. The “write end” handle for the output pipe and the “read end” handle for the input pipe are assigned to this START_INFO structure’s hStdOut and hStdInput members (respectively)
- The specified process is started and a reference to its handle is kept by our app to be used later when we want to close it or wait for it to exit
- A background thread is started which uses PeekNamedPipe to check to see if there is any data waiting to be read from the output pipe (using the “read end” handle we got from CreatePipe) – if there is then it uses ReadFile to read from the pipe and write it to a textbox on our window until no more data is waiting to be read.
- Once all data has been read from the output the thread uses WaitForMultipleObjects to wait for either the child process to terminate or for a ManualResetEvent to receive a signal – this signal is sent by other parts of our app when we want the background thread to check for output again and write it to the textbox. A timeout is also used so that after 10 seconds of waiting the thread checks to see if any data is available in the output pipe again anyway, just to make sure we do not miss anything.
- That is pretty much it for the output side of things – the input side is quite straight forward, simply using WriteFile to write to the “write end” of the input pipe we created with CreatePipe. Once input has been written, we signal the ManualResetEvent to make the background thread check for any output and display it on screen.
For more details, look at the source code as I have put a large amount of comments in it… and as always if you have any suggestions or questions then feel free to leave a comment here or on vbforums.