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

Windows下 C++ 实现匿名管道的读写操作的更多相关文章

  1. 解决windows下的mysql匿名登陆无法使用mysql数据库的问题

    原文:解决windows下的mysql匿名登陆无法使用mysql数据库的问题 我在windows下安装了mysql,但是不用密码就能登进去,而root明明是有密码的,我用select user()命令 ...

  2. windows下使用TortoiseGit代替Git命令行操作

    windows下使用TortoiseGit代替Git命令行操作 大家在使用svn的时候,都非常喜欢使用小乌龟,也就是TortoiseSVN:那么git也有小乌龟版本,即TortoiseGit. 1.安 ...

  3. Windows下安装kubectl及Node和Pod操作常用命令

    kubernetes通过kube-apiserver作为整个集群管理的入口.Apiserver是整个集群的主管理节点,用户通过Apiserver配置和组织集群,同时集群中各个节点同etcd存储的交互也 ...

  4. libevent实现对管道的读写操作

    读管道: #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/t ...

  5. Qt下libusb-win32的使用(二)批量读写操作

    一.概述 学习libusb-win32的使用.使用批量传输方式与USB开发板进行数据读.写操作.上位机使用Qt做界面, 使用USB开发板的端点2作为批量传输端点. 二.实现 代码比较简单,直接给出,如 ...

  6. windows 下使用批处理执行 postgresql 命令行操作

    1.准备好命令文件 loraserver.sql create role loraserver_as with login password 'dbpassword'; create role lor ...

  7. linux内核情景分析之匿名管道

    管道的机制由pipe()创建,由pipe()所建立的管道两端都在同一进程.所以必须在fork的配合下,才可以在具有亲缘关系的进程通信 /* * sys_pipe() is the normal C c ...

  8. C语言的可变参数在Linux(Ubuntu)与Windows下注意点

    基本上C语言的可变参数原理在不同平台和不同编译器下基本类似(通过函数入栈,从右向左,从高位到低位地址),不过部分实现会有所不同:在使用中需要注意的是: va_list 为char 类型指针,部分调用如 ...

  9. windows下的socket网络编程

    windows下的socket网络编程 windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了, ...

随机推荐

  1. [原创]android使用代码生成LayerDrawable的方法和注意事项

    为了有更好的UI体验,一般我们会把button.textview等控件的背景设置上阴影.传统的做法是美工提供一张具有阴影效果的nine patch图,然后将其在xml文件中添加到background属 ...

  2. iOS AVKit音视频播放全面详解

    公司项目中经常要用到音视频处理,也需要去定制一些东西,然后整理这些音视频处理就显得尤为重要!方便自己和广大朋友学习收藏! 以下参考连接特别重要: 苹果官方:AVKit API 苹果官方:AVFound ...

  3. 实例详解 DB2 排序监控和调优

    实例详解 DB2 排序监控和调优http://automationqa.com/forum.php?mod=viewthread&tid=2882&fromuid=2

  4. CSS基础(三):选择器

    常用选择器 元素选择器,即html标记如div,ul,li,p,h1~h6,table等. p { font-size:14px; } h1 { color:#F00; } 复合选择器, 由两个选择器 ...

  5. js 事件捕获与事件冒泡例子

    http://codepen.io/huashiyiqike/pen/qZVdag addEventListener 默认是冒泡阶段执行,也就是父亲与子都监听时,点击子,子先处理,父亲再处理,这时加s ...

  6. C#连接mysql数据库插入数据后获取自增长主键ID值

    From: http://blog.csdn.net/zbc496218/article/details/51082983 MySqlConnection conn = new MySqlConnec ...

  7. MemCached用法

    所需要的jar包: com.danga.MemCached.MemCachedClient com.danga.MemCached.SockIOPool 自行下载/** * 缓存服务器集群,提供缓存连 ...

  8. PHP 常见语法 集合

    1.die()与exit()的真正区别 die 为 exit 的别名, 执行过程 将释放内存,停止代码执行 echo "begin exec <br/>"; show( ...

  9. net组件转化成COM组件

    第一步:生成秘钥文件 强名称工具 (Sn.exe) 有助于使用强名称对程序集进行签名.Sn.exe 提供了用于密钥管理.签名生成和签名验证的选项. 1.使用Visual Studio 命令 Visua ...

  10. java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单

    一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...