MFC匿名管道原理详解、函数总结、调用实例(用MFC的匿名管道读取CMD输出内容)(C++语言)
本博客主要总结MFC中匿名管道的原理和具体调用实例,以及调用匿名管道三个核心函数各个参数用法详解,具体的如下所述。
博主在做项目时,遇到一个问题。用程序调用一个进程,然后读取进程输出信息。但是,博主用Qt的QProcess无法读取标准输出,所以只能考虑管道技术。
由于博主的开发环境是Windows10 64位,Qt的QProcess并没有找到类似的功能(可能博主对Qt研究不够深入,希望知道的大神告知一下),所以打算用MFC的匿名管道。
经过资料的查找和验证,博主发现,MFC的匿名管道技术可以实现读取CMD进程输出的内容,所以特定将MFC匿名管道用法记录下来,学习和总结。
匿名管道概念解释:
匿名管道主要用于进程间通信,进程的关系为父进程和子进程。具体原理如下图所示:
父进程和子进程都有读端口和写端口。通信方式可以从父进程写数据,子进程读数据。或者子进程写数据,父进程读数据。
其中,本文下面的例子是用图二的从子进程写数据,从父进程读取数据。即子进程通过cmd命令执行程序,然后程序输入的内容通过写句柄hWritePipe,写入内核(直接调用CrateProcess()函数,设置对应参数就可以写数据到内核。而不用调用WriteFile()函数)。父进程根据子进程管道的读句柄hReadPipe,调用ReadFile()函数读取内核数据。
一、MFC创建管道主要步骤
用MFC编写匿名管道的核心函数有三个,分别是CreatePipe(),CreateProcess(),ReadFile()三个核心函数。其中,函数CreatePipe()主要功能是创建一个管道通信,函数CreateProcess()主要功能是创建一个进程,函数ReadFile()读取进程输出的内容。下面是对创建管道通信步骤的总结:
1.1先创建调用函数CreatePipe()创建一个管道通信。关键代码为:
CreatePipe(&hReadPipe, &hWritePipe, &safety, 0);
1.2调用函数CreateProcess()创建一个进程,该进程输出的内容作为管道的写端口,向管道写数据。关键代码为:(其中写的句柄hWritePipe在结构体startInfo里的参数设置)
CreateProcess(NULL, cmdStr, NULL, NULL, TRUE, NULL, NULL, NULL, &startupInfo, &pinfo);
1.3调用函数ReadFile()作为管道的读端口,读取进程写入管道的内容。关键代码为:(其中读取内存存在缓冲区buffer)
ReadFile(hReadPipe, buffer, 4095, &byteRead, NULL);
1.4下面是博主封装的一个函数。该函数的功能是输入cmd命令,返回cmd输出内容。
具体代码如下所示:
CString executeCmd(CString command)
{
//创建匿名管道
HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES safety; //安全属性
safety.nLength = sizeof(SECURITY_ATTRIBUTES); //结构体大小
safety.lpSecurityDescriptor = NULL; //安全描述符,NULL;使用默认的
safety.bInheritHandle = TRUE; //安全描述符的对象能否被子进程继承
if (!CreatePipe(&hReadPipe, &hWritePipe, &safety, 0))
{
//创建管道错误
return _T("创建管道错误!");
}
//创建进程
TCHAR *cmdStr = StringToChar(command);
STARTUPINFO startupInfo = { sizeof(startupInfo) }; //进程信息
startupInfo.hStdError = hWritePipe; //标志控制台窗口缓存
startupInfo.hStdOutput = hWritePipe; //标志控制台窗口缓存
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; //使用wSHOWWIndows成员
startupInfo.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pinfo;
if (!CreateProcess(NULL, cmdStr, NULL, NULL, TRUE, NULL, NULL, NULL, &startupInfo, &pinfo))
{
//创建进程错误
return _T("创建进程错误!");
}
CloseHandle(hWritePipe);
//获取管道信息
char buffer[4096];
DWORD byteRead;
CString output; //返回值
while (true)
{
memset(buffer, 0, 4096); //要放在循环里面,否则接收数据错乱
if (ReadFile(hReadPipe, buffer, 4095, &byteRead, NULL) == NULL)
{
break;
}
output += buffer;
}
CloseHandle(hReadPipe);
return output;
}
TCHAR* StringToChar(CString& str)
{
int len = str.GetLength();
TCHAR* tr = str.GetBuffer(len);
str.ReleaseBuffer();
return tr;
}
1.5函数调用的一个实例
CString cmdString = _T("ipconfig.exe /?");
CString output = executeCmd(cmdString);
AfxMessageBox(output);
1.6运行结果如下图所示:
二、关键函数参数讲解
2.1函数CreatePipe()各个参数如下所示:
BOOL CreatePipe(
_Out_ PHANDLE hReadPipe, //管道读端口句柄
_Out_ PHANDLE hWritePipe, //管道写端口句柄
_In_opt_ LPSECURITY_ATTRIBUTES lpPipeAttributes, //安全描述符,通过设置参数,可以设置能否被支线程继承
_In_ DWORD nSize //0表示管道缓冲设置为系统默认值
);
2.2函数CreateProcess()各个参数如下所示:
BOOL CreateProcess(
_In_opt_ LPCWSTR lpApplicationName, //指向要调用的程序路径
_Inout_opt_ LPWSTR lpCommandLine, //输入的命令行TCHAR*字符串
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, //结构体SECURTY_ATTRIBUTE,指向进程安全描述符
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, //结构体SECURITY_ATTRIBUTE,指向线程安全描述符
_In_ BOOL bInheritHandles, //新进程是否从调用进程处继承了句柄
_In_ DWORD dwCreationFlags, //附加的、用来控制优先类和进程的创建标志。设置为CREATE_NEW_CONSOLE可显示子窗口。
_In_opt_ LPVOID lpEnvironment, //指向使用父类的环境
_In_opt_ LPCWSTR lpCurrentDirectory, //使用父类的当前目录
_In_ LPSTARTUPINFOW lpStartupInfo, //结构体STARTUPINFO,指向一个用于决定新进程的主窗体如何显示
_Out_ LPPROCESS_INFORMATION lpProcessInformation //结构体PROCESS_INFORMATION,指向一个用来接收新进程的识别信息
);
2.3函数ReadFile()各个参数如下所示:
BOOL ReadFile(
_In_ HANDLE hFile, //文件句柄
_Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer, //读缓冲区
_In_ DWORD nNumberOfBytesToRead, //要读取的字节数
_Out_opt_ LPDWORD lpNumberOfBytesRead, //实际读取到的字节数
_Inout_opt_ LPOVERLAPPED lpOverlapped //指向结构体OVERLAPPED,一般设为NULL
);
参考内容:
https://blog.csdn.net/it2153534/article/details/79064643(参考:重点函数各个参数讲解)
https://blog.csdn.net/qq61394323/article/details/39829631(参考:MFC读取CMD输出内容代码)
https://blog.csdn.net/qq61394323/article/details/39253193?utm_source=blogxgwz2(参考:匿名管道读写句柄用法)
https://blog.csdn.net/whynottrythis/article/details/39828395(参考:STARTUPINFO结构体各个参数讲解)
https://blog.csdn.net/jeanphorn/article/details/44982273(参考:函数ReadFile()参数讲解和调用实例,主要参考)
https://blog.csdn.net/virtualdesk/article/details/4379965(参考:函数ReadFile()参数讲解和调用实例)
原文:https://blog.csdn.net/naibozhuan3744/article/details/83142860
MFC匿名管道原理详解、函数总结、调用实例(用MFC的匿名管道读取CMD输出内容)(C++语言)相关推荐
- 偏最小二乘回归分析原理详解和案例分析实例
偏最小二乘回归分析原理详解 背景 偏最小二乘回归分析 Partial least squares regression analysis 基本思想 建模步骤 步骤一:分别提取两变量组的第一对成分,并使 ...
- XSS(跨站脚本攻击)原理详解(内含攻击实例)
环境: 军锋真人cs野战123平台.xss平台(推荐自行搭建xss平台,不让别人白嫖咱自个的成果,蓝莲花战队的那个就挺好).webshell箱子.postman.beef(kali上可能要自行下载,三 ...
- python函数定义及调用-python函数声明和调用定义及原理详解
这篇文章主要介绍了python函数声明和调用定义及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 函数是指代码片段,可以重复调用,比如我们前 ...
- Sklearn中predict_proba函数用法及原理详解
Sklearn中predict_proba函数用法及原理详解(以logistic回归为例) 网上对predict_proba的数学原理解释的太少了,也不明确,特意总结一下,并给出有些不能用该方法的原因 ...
- python函数声明和调用定义及原理详解
这篇文章主要介绍了python函数声明和调用定义及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 函数是指代码片段,可以重复调用,比如我们前 ...
- jQuery中getJSON跨域原理详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...
- ASP.NET页面与IIS底层交互和工作原理详解 (二)
第三回: 引言 Http 请求处理流程 和 Http Handler 介绍 这两篇文章里,我们首先了解了Http请求在服务器端的处理流程,随后我们知道Http请求最终会由实现了IHttpHandler ...
- CRF(条件随机场)与Viterbi(维特比)算法原理详解
摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...
- EMD算法之Hilbert-Huang Transform原理详解和案例分析
目录 Hilbert-Huang Transform 希尔伯特-黄变换 Section I 人物简介 Section II Hilbert-Huang的应用领域 Section III Hilbert ...
最新文章
- 如何使用其他文件中定义的类Python
- Android下资源图片的加密和解密
- c语言流程图char,求救!各位大神,用程序流程图怎么描述下面这个???
- 开发提交审核流程_小程序如何提交审核,多久能通过?
- C# DataTable用法详解
- maven使用testng_使用ReportNG更好看的TestNG HTML测试报告– Maven指南
- java获取数组的最小值_Java 数组获取最大和最小值的实例实现
- 前端学习(1427):ajax封装二
- HTML,,,音乐,html embed用法
- 查看ipad网页代码 iPad Quick Tip – View Page Source In iPad Safari
- python时间序列滞后命令,时间序列-相关性和滞后时间
- 关于单元测试的思考--Asp.Net Core单元测试最佳实践
- 运行opencv保存视频时出现错误的解决方法
- Android下Cocos2d创建HelloWorld工程
- linux从表中提取信息,如何用Linux命令提取表格文本中的某列
- 如何利用回调模式去解决问题
- Java、JSP网吧自动计费收费管理系统
- 计算机科学精粹这本书有用吗,计算机科学精粹
- ONES 万事联合创始人 \u0026 CTO 冯斌:企业服务产品的探索实践
- spring-context.xml
热门文章
- python学习-综合练习四(最大公约数、最小公倍数、生成日历、递归调用、字符串)
- kafka常见的问题(具体详细)
- html不用点击自动执行,页面自动执行(加载)js的几种方法
- windows 取色器_这款 Windows 10 官方「外挂」让你取色更便捷
- MATLAB 长度和像素_MATLAB——单车道NaSch模型
- 公差基本偏差代号_螺纹基础知识学习,螺纹公差标准的结构,螺纹公差带与旋合长度...
- 16x16x16 4096个RGB LED的光立方是一种怎样的神奇效果?视频展示制作全过程
- 老兵传奇:聊聊我在华为的20年
- python学习之turtle库基本操作
- linux终端进程bash,让Linux的进程不受终端影响