本博客主要总结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++语言)相关推荐

  1. 偏最小二乘回归分析原理详解和案例分析实例

    偏最小二乘回归分析原理详解 背景 偏最小二乘回归分析 Partial least squares regression analysis 基本思想 建模步骤 步骤一:分别提取两变量组的第一对成分,并使 ...

  2. XSS(跨站脚本攻击)原理详解(内含攻击实例)

    环境: 军锋真人cs野战123平台.xss平台(推荐自行搭建xss平台,不让别人白嫖咱自个的成果,蓝莲花战队的那个就挺好).webshell箱子.postman.beef(kali上可能要自行下载,三 ...

  3. python函数定义及调用-python函数声明和调用定义及原理详解

    这篇文章主要介绍了python函数声明和调用定义及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 函数是指代码片段,可以重复调用,比如我们前 ...

  4. Sklearn中predict_proba函数用法及原理详解

    Sklearn中predict_proba函数用法及原理详解(以logistic回归为例) 网上对predict_proba的数学原理解释的太少了,也不明确,特意总结一下,并给出有些不能用该方法的原因 ...

  5. python函数声明和调用定义及原理详解

    这篇文章主要介绍了python函数声明和调用定义及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 函数是指代码片段,可以重复调用,比如我们前 ...

  6. jQuery中getJSON跨域原理详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...

  7. ASP.NET页面与IIS底层交互和工作原理详解 (二)

    第三回: 引言 Http 请求处理流程 和 Http Handler 介绍 这两篇文章里,我们首先了解了Http请求在服务器端的处理流程,随后我们知道Http请求最终会由实现了IHttpHandler ...

  8. CRF(条件随机场)与Viterbi(维特比)算法原理详解

    摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...

  9. EMD算法之Hilbert-Huang Transform原理详解和案例分析

    目录 Hilbert-Huang Transform 希尔伯特-黄变换 Section I 人物简介 Section II Hilbert-Huang的应用领域 Section III Hilbert ...

最新文章

  1. 如何使用其他文件中定义的类Python
  2. Android下资源图片的加密和解密
  3. c语言流程图char,求救!各位大神,用程序流程图怎么描述下面这个???
  4. 开发提交审核流程_小程序如何提交审核,多久能通过?
  5. C# DataTable用法详解
  6. maven使用testng_使用ReportNG更好看的TestNG HTML测试报告– Maven指南
  7. java获取数组的最小值_Java 数组获取最大和最小值的实例实现
  8. 前端学习(1427):ajax封装二
  9. HTML,,,音乐,html embed用法
  10. 查看ipad网页代码 iPad Quick Tip – View Page Source In iPad Safari
  11. python时间序列滞后命令,时间序列-相关性和滞后时间
  12. 关于单元测试的思考--Asp.Net Core单元测试最佳实践
  13. 运行opencv保存视频时出现错误的解决方法
  14. Android下Cocos2d创建HelloWorld工程
  15. linux从表中提取信息,如何用Linux命令提取表格文本中的某列
  16. 如何利用回调模式去解决问题
  17. Java、JSP网吧自动计费收费管理系统
  18. 计算机科学精粹这本书有用吗,计算机科学精粹
  19. ONES 万事联合创始人 \u0026 CTO 冯斌:企业服务产品的探索实践
  20. spring-context.xml

热门文章

  1. python学习-综合练习四(最大公约数、最小公倍数、生成日历、递归调用、字符串)
  2. kafka常见的问题(具体详细)
  3. html不用点击自动执行,页面自动执行(加载)js的几种方法
  4. windows 取色器_这款 Windows 10 官方「外挂」让你取色更便捷
  5. MATLAB 长度和像素_MATLAB——单车道NaSch模型
  6. 公差基本偏差代号_螺纹基础知识学习,螺纹公差标准的结构,螺纹公差带与旋合长度...
  7. 16x16x16 4096个RGB LED的光立方是一种怎样的神奇效果?视频展示制作全过程
  8. 老兵传奇:聊聊我在华为的20年
  9. python学习之turtle库基本操作
  10. linux终端进程bash,让Linux的进程不受终端影响