由于刚弄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. drupal module 自定义

    01 <?php function mytracer_menu() { $items = array(); $items['admin/config/mytracer'] = array( 't ...

  2. Hive Streaming 追加 ORC 文件

    1.概述 在存储业务数据的时候,随着业务的增长,Hive 表存储在 HDFS 的上的数据会随时间的增加而增加,而以 Text 文本格式存储在 HDFS 上,所消耗的容量资源巨大.那么,我们需要有一种方 ...

  3. Java开发者值得关注的7款新工具

    云计算.大数据地快速发展催生了不少热门的应用及工具.作为老牌语言Java,其生态圈也出来了一些有关云服务.监控.文档分享方面的工具.本文总结了7款较新的Java工具,大家不妨看下. 1. JClari ...

  4. 增大VM下linux的根目录空间

    增大VM下linux的根目录空间   用的太久,发现VM下的系统空间不足.简单的方法是,分一个新硬盘,挂载到根目录下.    下面是直接增大根目录下空间:  1. 增大vm下的磁盘大小, VM -&g ...

  5. [论文笔记] Legacy Application Migration to the Cloud: Practicability and Methodology (SERVICES, 2012)

    Quang Hieu Vu, Rasool Asal: Legacy Application Migration to the Cloud: Practicability and Methodolog ...

  6. 在unity5中减少Draw Calls(SetPass Calls)[转]

    在unity5中减少Draw Calls(SetPass Calls)   我一直工作于unity5支持的Standard Shader(标准着色器)上,并且做了一些关于如何有效地减少draw cal ...

  7. JavaScript的9个陷阱及评点

    1. 最后一个逗号 如这段代码,注意最后一个逗号,按语言学角度来说应该是不错的(python的类似数据类型辞典dictionary就允许如此).IE会报语法错误,但语焉不详,你只能用人眼从几千行代码中 ...

  8. 轻量级IOC框架:Ninject (下)

    一,创建依赖链(Chains of Dependency) 当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系.如果有额外的依赖,Ninject也会解析它们 ...

  9. EventKit 学习(译)

    From:http://docs.xamarin.com/guides/ios/platform_features/introduction_to_eventkit/ 本教程展示了对于如何通过Even ...

  10. 单链表List的C实现

    头文件———————————————————————————————— //单链表的实现 #ifndef _LIST_H_ #define _LIST_H_ #include <stdlib.h ...