• 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++

  • 相关阅读:
    牛券
    探险
    雷达安装
    智力大冲浪
    奶牛玩杂技
    BJWC2008 秦腾与教学评估
    JSOI2010 部落划分
    作诗
    ASP.NET MVC4系列验证机制、伙伴类共享源数据信息(数据注解和验证)
    正则表达式
  • 原文地址:https://www.cnblogs.com/suwings/p/5754943.html
Copyright © 2020-2023  润新知