因爲剛弄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++對象