21
votes

I need to get (or pipe) the output from a process that is already running, using the windows api.

Basically my application should allow the user to select a window to pipe the input from, and all input will be displayed in a console. I would also be looking on how to get a pipe on stderr later on.

Important: I did not start the process using CreateProcess() or otherwise. The process is already running, and all I have is the handle to the process (returned from GetWindowThreadProcessId()).

3
As Adam says, almost certainly the wrong thing to do. Can you describe what you are trying to achieve? Are you sure the application even has any output? Most GUI processes don't. - Harry Johnston
@HarryJohnston It's a Java application which has console output. - David
In that case, it may be possible to modify the Java runtime to achieve your purpose. I still wouldn't recommend it, but it may be possible. - Harry Johnston
This answer may be useful to anyone coming across this question: stackoverflow.com/a/54317865/153844 - cmann

3 Answers

3
votes

The cleanest way of doing this without causing any ill effects, such that may occur if you used the method Adam implied of swapping the existing stdout handle with your own, is to use hooking.

If you inject a thread into the existing application and swap calls to WriteFile with an intercepted version that will first give you a copy of what's being written (filtered by handle, source, whatever) then pass it along to the real ::WriteFile with no harm done. Or you can intercept the call higher up by only swapping out printf or whichever call it is that the software is using (some experimentation needed, obviously).

HOWEVER, Adam is spot-on when he says this isn't what you want to do. This is a last resort, so think very, very carefully before going down this line!

0
votes

Came across this article from MS while searching on the topic. http://support.microsoft.com/kb/190351

The concept of piping input and output on Unix is trivial, there seems no great reason for it to be so complex on Windows. - Karl

-9
votes

Whatever you're trying to do, you're doing it wrong. If you're interacting with a program for which you have the source code, create a defined interface for your IPC: create a socket, a named pipe, windows messaging, shared memory segment, COM server, or whatever your preferred IPC mechanism is. Do not try to graft IPC onto a program that wasn't intending to do IPC.

You have no control over how that process's stdout was set up, and it is not yours to mess with. It was created by its parent process and handed off to the child, and from there on out, it's in control of the child. You don't go in and change the carpets in somebody else's house.

Do not even think of going into that process, trying to CloseHandle its stdout, and CreateFile a new stdout pointing to your pipe. That's a recipe for disaster and will result in quirky behavior and "impossible" crashes.

Even if you could do what you wanted to do, what would happen if two programs did this?