Windows下 C++ 實現匿名管道的讀寫操做

因爲剛弄C++沒多久,部分還不熟練,最近又因爲開發需求要求實現與其餘程序進行通訊,瞬間就感受想到了匿名通訊。因而本身查閱了一下資料,實現了一個可讀可寫的匿名管道:ios

源代碼大部分都有註釋:windows

 

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.cppoop

 

 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 }

 

這樣便可實現 與任何程序進行交互:固然了也能夠不單單是 輸入輸出this

咱們這裏執行cmd;spa

結果:線程

而且能夠進行交互:code

 

差很少就這樣,大神勿噴,我纔剛弄C++對象

相關文章
相關標籤/搜索