由于刚弄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. vs多项目模板及add-in开发

    本文分2部分 第一为自定义多项目模板 第二为vs add-in开发 效果图 1.自定义模板 2. 工具菜单 3.窗口 4.工程 5.文件 ... 一. 多项目模板 单项目模板做起来很简单 选中一个项目 ...

  2. android 监听软键盘的收起与打开

    参考: http://toughcoder.net/blog/2015/10/09/android-trick-detect-soft-keyboard-show-slash-hide/ packag ...

  3. Spring MVC 事务配置

    Spring MVC事务配置 要了解事务配置的所有方法,请看一下<Spring事务配置的5种方法> 本文介绍两种配置方法: 一.      XML,使用tx标签配置拦截器实现事务 一.   ...

  4. Spark源码系列(一)spark-submit提交作业过程

    前言 折腾了很久,终于开始学习Spark的源码了,第一篇我打算讲一下Spark作业的提交过程. 这个是Spark的App运行图,它通过一个Driver来和集群通信,集群负责作业的分配.今天我要讲的是如 ...

  5. BeginInvoke与Invoke的区别

    简单的讲就是 BeginInvoke不需要等待方法运行完毕,就会继续执行下面的代码 Invoke则必须等待Invoke中的代码运行完毕,才会继续执行下面的代码. 可以通过下面的项目测试上面所描述的观点 ...

  6. 用对 gitignore

    使用 git 做代码管理工具时,设置 gitignore 是必不可少的流程,一些系统或者 IDE 会在目录下生成与项目不相关的文件,而这些文件我们不期望被提交到仓库之中.理解 gitignore 的 ...

  7. 使用Merge Into 语句实现 Insert/Update

    网址: http://www.eygle.com/digest/2009/01/merge_into_insertupdate.html 动机: 想在Oracle中用一条SQL语句直接进行Insert ...

  8. easyui menubutton combobox 被遮盖问题

    如图一所示,menubutton 中的 combobox 被遮盖 z-Index 不够.这是作者给出的解决方案 <a href="#" class="easyui- ...

  9. 利用SSIS发送邮件

    璎Nicole珞 博客园 闪存 首页 新随笔 联系 管理 订阅 随笔- 15  文章- 0  评论- 0  SSIS 利用发送邮件服务 Send Email Task   1. 在SSIS中如何发送邮 ...

  10. STM32 程序所占用空间计算 && FLASH存储的起始地址计算

    程序编译完成,会乘车program size .. 对STM32容量选型或者 计算FLASH 充当EEPROM起始地址时会用到此参数. 按照下面截图  程序空间 = (16700+732+4580)/ ...