本篇文章主要介绍windows下如何将一个应用程序的输出重定向到另一个进程中,主要原理是通过匿名管道实现进程信息的重定向。
工作中有时会遇到这样一个场景,应用程序A.exe需要调用应用程序B.exe进行一些辅助性操作,同时,A还需要获取B执行后的输出结果,以便于在A中根据B的输出结果进行相关的操作。本文主要解决的就是上述问题。以iperf为例,iperf是一个网络吞吐量测试工具,它可以测试当前的网络状况。本文使用一个控制台程序(A.exe)调用iperf.exe(B.exe)进行网络性能测试,然后将iperf.exe的输出信息重定位到A的控制台窗口进行输出。
系统环境:Win10_x64、VS2017
内容安排:
一、下载iperf;
二、代码实现。
一、下载iperf
1.iperf下载地址:Iperf for Windows
下载iperf后将解压得到的iperf3.exe、cygwin1.dll放入对应项目目录下供应用程序A调用。
注:简单起见,建议重定向你自己的exe文件而不是iperf,这只需要修改main函数中的命令行即可。
二、代码实现
代码利用匿名管道实现输出重定向,其中对重定向部分的代码进行了封装,便于调用。下面给出具体实现:
1.封装类cmdhandler.h实现:
#ifndef __CMD_HANDLER_H__
#define __CMD_HANDLER_H__
#include <Windows.h>
#include <string>
/* buffer的最大长度 */
#define PIPE_BUFFER_SIZE 4096
#define PORT 12306
/* 命令参数 */
typedef struct _CHCmdParam CHCmdParam;
struct _CHCmdParam
{
/* 初始化为 sizeof(CommandParam) */
int iSize;
/* 外部命令,不需要用则设置为-1, 提供给外部使用
*/
int iCommand;
/* 超时时间,单位秒 */
long long iTimeOut;
/* 命令行要执行的命令 */
char* szCommand;
/* 用户数据 */
void* pUserData;
/* 命令执行后的回调 */
void(*OnCmdEvent)(const CHCmdParam* pParam, HRESULT hResultCode, char* szResult);
};
class CCmdHandler
{
private:
BOOL m_bInit;
DWORD m_port;
STARTUPINFO m_startupInfo;
PROCESS_INFORMATION m_processInfo;
SECURITY_ATTRIBUTES m_saOutPipe;
DWORD m_dwErrorCode;
HANDLE m_hPipeRead;
HANDLE m_hPipeWrite;
CHCmdParam m_CommandParam;
TCHAR m_szReadBuffer[PIPE_BUFFER_SIZE];
TCHAR m_szWriteBuffer[PIPE_BUFFER_SIZE];
char m_szPipeOut[PIPE_BUFFER_SIZE];
HRESULT ExecuteCmdWait();
public:
CCmdHandler();
~CCmdHandler();
/*
* 客户端初始化接口,调用其余接口之前调用
* 成功返回S_OK
*/
HRESULT Cli_Initalize();
/*
* 服务器初始化接口,调用其余接口之前调用
* 成功返