Windows下 C++ 实现匿名管道的读写操作

由于刚弄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;

结果:

并且可以进行交互:

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

原文地址:https://www.cnblogs.com/suwings/p/5754943.html