Grab Program's Console Output
I am creating a network administration program for a company I'm currently doing some contract work with (irrelevant I suppose)
As part of the program,开发者_如何学编程 I would like to have a console/telnet(type) clone. I have a working directory system, where I can essentially read all files in directories, and change directories. I also have an easy FTP protocol set up. However I would like to arbitrarily speak to different programs with the standard input/output procedures programmatically. I'm not opposed to DLL injection techniques, and other methods, as this is a benign program. If possible it would be awesome if I could just directly use the console easily. (system() would possibly work, however this doesn't allow continued communication or reading back of output)
I'm thinking so far of grabbing the PATH environment vars and utilizing that for std commands (ipconfig, netstat, etc) My networking library makes communication easy, but I'm just not sure how to interface with the program's console...
TL;DR:
Are there any predefined ways of standard console communication between programs?
As Jerry mentioned, what you're looking for is a pipe (CreatePipe). Two of them actually - one for input and one for output. You then create the new process with them set as stdin/stdout/stderr in STARTUPINFO passed to CreateProcess. You can then use WriteFile, ReadFile, PeekNamedPipe and friends to communicate.
A complete example is available on MSDN:
http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx
And make sure you don't fall into these common pitfalls (which luckily Raymond Chen just happened to document recently):
- http://blogs.msdn.com/b/oldnewthing/archive/2011/07/07/10183884.aspx
- http://blogs.msdn.com/b/oldnewthing/archive/2011/07/06/10183368.aspx
- http://blogs.msdn.com/b/oldnewthing/archive/2011/07/08/10184375.aspx
PS, this is sooooo much easier in Python with the subprocess module.
The easiest way is usually to spawn the child program with _popen
. This will give you a handle to write to the child's standard input, or read from the child's standard output.
If you need to do both, things get a lot uglier in a hurry. You usually have to create the anonymous pipes yourself and specify them in a call to CreateProcess
, which is, frankly, a pain.
Alright I've learned a TON about this in the last little while. And here's some information that some people may find useful =]
Code To Create Process With Pipes/File Descriptors as Stdin/out/err:
STARTUPINFO startInfo;
PROCESS_INFORMATION procInfo;
memset((void*) &startInfo, 0, sizeof (startInfo));
memset((void*) &procInfo, 0, sizeof (procInfo));
startInfo.cb = sizeof (startInfo);
startInfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
startInfo.wShowWindow = SW_HIDE; //No Console Window, Thanks.
startInfo.hStdInput = (HANDLE)inHandle;
startInfo.hStdOutput = (HANDLE)outHandle;
startInfo.hStdError = (HANDLE)errHandle;
char* pe = "cmd\0";
//This is the program to execute (eg: c:\\Windows\\System32\\cmd.exe)
CreateProcess(NULL,pe,NULL,NULL,TRUE,0,NULL,NULL,&startInfo,&procInfo);
return procInfo.hProcess;
Now this is all fine and dandy, but there's an additional little tidbit of information that has really helped me out here. You can use file descriptors for your handles (in/out/err) so you can use straight sockets, with no modification, and you will have direct access to the input and output of the process.
So my current method of creating a hidden console, is to connect two sockets together locally, then use one of the sockets as the stdInput && stdOutput && stdError descriptors for a child program that calls cmd. It's quick, and easy.
If you don't know how to connect some sockets together, just look into beej's guide
精彩评论