在信息化非常发达的今天,可能已经过了江湖“武侠”草莽的时代。仅凭一己之力想完成惊人的创举,可谓难上加难。于是 会分工越来越明确:你擅长写驱动,你就去封装个驱动出来;他擅长写界面,就让他写套界面出来。如果你非常好心,可以将自己的研究成果开源,那么可能会有千万人受益。如果你想保持神秘感,但是还是希望别人可以分享你的成果,你可能会将模块封装出来供别人使用。比如你提供了一个DLL文件和调用方法样例。但是,实际情况并不是我们想的那么简单。比如我文前提到的问题:别人提供了一个Console控制台程序,我们将如何获取其执行的输出结果呢个问题,从微软以为为我们考虑过了,我们可以从一个API中可以找到一些端倪——CreateProcess。
做Windows开发的同学对CreateProcess这个API应该非常眼熟,也应该经常调用过。但是仔细研究过这个API每个参数的同学应该不会太多吧。这个API的参数非常多,我想我们工程中对CreateProcess的调用可能就关注于程序路径(lpApplicationName),或者命令行(lpCommandLine)。而其他参数我们可能就保守的选择了NULL。(遥想2年前,我就是在这个API上栽了一个大大的跟头。)
粗看该结构体,我们可以知道:我们可以通过它控制子窗口出现的位置和大小还有显示方式。但是细看下它最后三个参数:StdInput、StdOutput和StdError。这三个参数似乎就点中了标题中的两个关键字“标准输出”、“标准错误输出”。是的!我们正是靠这几个参数来解决我们所遇到的问题。那么如何使用这些参数呢
我们选用的还是老方法——管道。 这儿我们创建一个管道,该管道提供两个句柄:hRead和hWrite。我们之后将hWrite交给我们创建的子进程,让它去将信息写入管道。而我们父进程,则使用hRead去读取子进程写入管道的内容。此处要注意的就是将SECURITY_ATTRIBUTES对象的bInheritHandle设置为TRUE,这样我们获取的两个操作管道的句柄就有可继承属性。为什么需要可继承属性,我们会在之后说明。 创建好管道后,我们将着手准备创建进程 此处我们要注意几个点:
- “Cmd..exe /C” 我们使用CMD运行我们代理的程序。注意,我们启动的是CMD,而不是我们传入的文件路径。关于CMD命令的说明如下:
- 设置标准输出和标准错误输出句柄
- 隐藏CMD控制台
- 设置有效属性
这两个有效属性要设置。我们设置STARTF_USESHOWWINDOW的原因是:我们要控制CMD窗口不出现,所以我们修改了wShowWindow属性。我们使用STARTF_USESTDHANDLES的原因是:我们使用了标准输出和标准错误输出句柄。此处我们还要特别将一下STARTF_USESTDHANDLES属性的说明,我们看MSDN有如下描述 也就是说,我们设置的这些句柄要有可继承性。这就解释了我们之前为什么在创建管道时要将句柄可继承性设置为TRUE的原因。
一般来说,我们要代理的程序已经输入好信息了。我们要关闭写管道 之后便是读取管道信息。我想应该有人借用过 上相似的代码,但是却发现一个问题,就是读取出来的信息是不全的。这个问题的关键就在读取的方法上,其实没什么玄妙,只要控制好读取起始位置就行了。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!