设为首页 收藏本站
查看: 875|回复: 0

[经验分享] Windows下 C++ 实现匿名管道的读写操作

[复制链接]

尚未签到

发表于 2017-6-28 12:00:21 | 显示全部楼层 |阅读模式
  由于刚弄C++没多久,部分还不熟练,最近又由于开发需求要求实现与其他程序进行通信,瞬间就感觉想到了匿名通信。于是自己查阅了一下资料,实现了一个可读可写的匿名管道:
  源代码大部分都有注释:
  Pipe.h 文件



#pragma once
#include <iostream>
#include <windows.h>

using namespace std;
class Pipe // 不可移植类,只限于 WindowsXP 以上 平台
{
private:
HANDLE hpiperead = NULL;   //读入 匿名管道
HANDLE hpipewrite = NULL;    //读入 匿名管道
HANDLE hpiperead2 = NULL;   //写出 匿名管道
HANDLE hpipewrite2 = NULL;    //写出 匿名管道
HANDLE hProHandle = NULL;
HANDLE hThrLoop = NULL;
HANDLE hThrisLoop = NULL;
SECURITY_ATTRIBUTES ai;     //安全属性
PROCESS_INFORMATION pi;    //进程信息
    STARTUPINFOA si;
BOOL pipe = false;
INT status = 1;  // 0 = 异常 1 = 正常 -1 = 错误 、
string errorString;
public:
void loop() ;    //循环
void isloop() ;    //循环
const BOOL isPipeOff() const;    //管道是否是开启
const INT getStatus() const;    //获取当前状况
const string & getError() const;    //获取当前错误信息
const BOOL sendCommand(const char *);    //执行命令
void setPipeOn(const BOOL);    //设置管道是否开启
void setStatus(const INT, const char*);    //用于设置错误信息
void setStatus(const INT);    //重载,用于设置状态
Pipe( char * str);        //管道执行的命令
~Pipe();
};
  Pipe.cpp 文件



  1 #include "Pipe.h"
  2
  3
  4 DWORD __stdcall ThrPipeThreadRead(void *www)
  5 {
  6     Pipe * pipe = (Pipe *)www;
  7     pipe->loop();
  8     return 0;
  9     //创建内核对象使用完之后一定记得关闭,有可能会产生内存泄露
10 }
11 DWORD __stdcall WaitPipe(void *www)
12 {
13     Pipe * pipe = (Pipe *)www;
14     pipe->isloop();
15     return 0;
16 }
17
18
19 Pipe::Pipe( char * com)
20 {
21     ai.nLength = sizeof(SECURITY_ATTRIBUTES);
22     ai.bInheritHandle = true;
23     ai.lpSecurityDescriptor = NULL;
24     if (!CreatePipe(&hpiperead, &hpipewrite, &ai, 0))  //创建读入管道
25     {
26     
27         this->setStatus(-1, "[0x01]Read 流创建失效");
28         return;
29     }
30     
31     if (!CreatePipe(&hpiperead2, &hpipewrite2, &ai, 0))  //创建读入管道
32     {
33         
34         this->setStatus(-1, "[0x02]Write 流创建失效");
35         return;
36     }
37     GetStartupInfoA(&si);    //获取当前进程的STARTUPINFO
38     si.cb = sizeof(STARTUPINFO);
39     si.hStdError = hpipewrite;
40     si.hStdOutput = hpipewrite;
41     si.hStdInput = hpiperead2;
42     si.wShowWindow = SW_SHOW;
43     si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
44     
45     if (!(CreateProcessA(NULL, com, NULL, NULL, true, NULL, NULL, NULL, &si, &pi)))      //创建隐藏的CMD进程
46     {
47         this->setStatus(-1, "[0x03] CreateProcess函数执行出错");
48         return;
49     }
50     
51     
52     DWORD dwThread = FALSE;
53     hThrLoop = CreateThread(NULL, 0, ThrPipeThreadRead, this, 0, &dwThread);//chuangjian
54     if (hThrLoop == false){
55         this->setStatus(-1, "[0x11] 线程创建失败 CreateThread LOOP 失败");
56         return;
57     }
58     hThrLoop = CreateThread(NULL, 0, WaitPipe, this, 0, &dwThread);//chuangjian
59     if (hThrLoop == false){
60         this->setStatus(-1, "[0x12] 线程创建失败 CreateThread ISLOOP失败");
61         return;
62     }
63 }
64
65
66
67
68 Pipe::~Pipe()
69 {
70     //创建内核对象使用完之后一定记得关闭,有可能会产生内存泄露
71     this->setPipeOn(false);
72     this->setStatus(-1);
73     CloseHandle(hThrisLoop);
74     CloseHandle(hThrLoop);
75     CloseHandle(hpipewrite);
76     CloseHandle(hpiperead);
77     CloseHandle(hpiperead2);
78     CloseHandle(hpipewrite2);
79     CloseHandle(pi.hProcess);
80     CloseHandle(pi.hThread);
81     
82 }
83 const INT Pipe::getStatus() const
84 {
85     return this->status;
86 }
87
88 const string & Pipe::getError() const
89 {
90     return this->errorString;
91 }
92
93 const BOOL Pipe::isPipeOff() const
94 {
95     return pipe;
96 }
97
98 void Pipe::setPipeOn(const BOOL bools)
99 {
100     this->pipe = bools;
101 }
102
103 void Pipe::setStatus(const INT status, const char * info)
104 {
105     this->errorString = info;    //你说会不会有更好的赋值方法?
106     this->status = status;
107 }
108
109 void Pipe::setStatus(const INT status = 1)
110 {
111     this->status = status;
112 }
113
114 const BOOL Pipe::sendCommand(const char * com)     //执行命令
115 {
116     DWORD dwWrite = 0;
117     char www[1024];
118     strcpy_s(www,com);
119     strcat_s(www,"\n");
120     return WriteFile(hpipewrite2, www, strlen(www), &dwWrite, NULL);
121         //0x001C7796 处有未经处理的异常(在 ConsoleApplication2.exe 中):  0xC0000005:  读取位置 0x0000000C 时发生访问冲突。
122 }
123
124 void Pipe::loop(){
125     char outbuff[4096];        //输出缓冲
126     DWORD byteread;
127     this->setPipeOn(true);
128     while (true)
129     {
130         memset(outbuff, '\0', 4096);
131         if (ReadFile(this->hpiperead, outbuff, 4095, &byteread, NULL) == NULL)
132         {
133             this->setPipeOn(false);
134             break;
135         }
136         printf("%s", outbuff);
137         memset(outbuff, '\0', 4096);
138     }
139     this->setPipeOn(false);
140     std::cout << "Pipe Stoped!"<<endl;
141 }
142
143 void Pipe::isloop()
144 {
145     DWORD dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
146     while (dwRet == WAIT_TIMEOUT)
147     {
148         dwRet = WaitForSingleObject(pi.hProcess, INFINITE);
149     }
150
151     if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED)
152     {
153         this->setPipeOn(false);
154         std::cout << "[END] Pipe Stoped!" << endl;
155     }
156 }
  Luncher.cpp



1 // ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
2 //
3 #include <windows.h>
4 #include <thread>
5 #include "Pipe.h"
6 using namespace std;
7
8 void read();
9 void Loop();
10
11 Pipe * pipe;        //属于全局变量
12
13
14 int Luncher()  //那个啥,你就是当作这是Main文件的Main方法不
15 {
16     thread t1(read);    //需要C++11标准
17     thread t2(Loop);
18
19     pipe = new Pipe("cmd");
20     t1.join();
21     t2.join();
22     return 0;
23 }
24 void read(){
25     
26     while (true){
27         char str[200];
28         cin >> str;
29         pipe->sendCommand(str);  //提交命令
30     }
31 }
32
33 void Loop(){
34     while (true)
35     {
36         Sleep(1000);
37         if (pipe->getStatus() == -11)
38         {
39             cout << " ERROR " << endl;
40             return;
41         }
42     }
43 }
  这样即可实现 与任何程序进行交互:当然了也可以不仅仅是 输入输出
  我们这里执行cmd;
  结果:
DSC0000.png

  并且可以进行交互:
DSC0001.png

  差不多就这样,大神勿喷,我才刚弄C++

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-388955-1-1.html 上篇帖子: Windows互斥锁demo和分析 下篇帖子: MySQL For Windows Zip解压版安装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表