實現原理:
管道是一種在進程間共享數據的機制,其實質是一段共享內存。Windows系統為這段共享的內存設計使用數據流I/O的方式來訪問。一個進程讀,另一個進程寫,這類似於一個管道的兩端,因此這種進程間的通信方式稱為“管道”。管道分為匿名管道和命名管道。匿名管道只能在父子進程間進行通信,不能在網絡間通信,而且數據傳輸是單向的,只能一端寫,另一端讀。命名管道可以在任意進程間通信,通信是雙向的,任意一端都可讀可寫,但是在同一時間只能有一端讀、一端寫。創建命名管道的方式可以獲取CMD執行結果的輸出內容
實現過程:
(1).調用函數CreatePipe創建匿名管道,獲取管道數據讀取句柄和管道數據寫入句柄。
(2).創建新進程(進程屬性為窗口隱藏、窗口的緩存句柄設置為上面得到的管道數據寫入句柄)
(3).調用函數WaitForSingleObject等待命令執行完畢
(4).調用ReadFile函數根據匿名管道的數據讀取句柄從匿名管道的緩沖區中讀取數據
(5).關閉句柄,釋放資源
實現代碼:
//************************************ // 函數名:CCmdDlg::PipeCmd // 返回類型:BOOL // 功能: 執行CMD命令, 並獲取執行結果數據 // 參數1:char *pszCmd cmd命令 // 參數2:char *pszResultBuffer 接收CMD結果的緩沖區 // 參數3:DWORD dwResultBufferSize 緩沖區大小(緩沖區要大點,不然接收到的結果不全) //************************************ BOOL CCmdDlg::PipeCmd(char *pszCmd, char *pszResultBuffer, DWORD dwResultBufferSize) { SECURITY_ATTRIBUTES securityAttributes = { 0 }; // 設定管道的安全屬性 securityAttributes.bInheritHandle = TRUE; securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; // 創建匿名管道 HANDLE hReadPipe = NULL; HANDLE hWritePipe = NULL; BOOL bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0); if (FALSE == bRet) { MessageBox(_T("CreatePipe Error")); return FALSE; } STARTUPINFO si = { 0 }; // 設置新進程參數 si.cb = sizeof(si); si.hStdError = hWritePipe; si.hStdOutput = hWritePipe; si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // 創建新進程執行命令, 將執行結果寫入匿名管道中 PROCESS_INFORMATION pi = { 0 }; USES_CONVERSION; bRet = ::CreateProcess(NULL, A2W(pszCmd), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if (FALSE == bRet) { MessageBox(_T("CreateProcess Error")); } // 等待命令執行結束 ::WaitForSingleObject(pi.hThread, INFINITE); ::WaitForSingleObject(pi.hProcess, INFINITE); // 從匿名管道中讀取結果到輸出緩沖區 ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize); ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, NULL, NULL); // 關閉句柄, 釋放內存 ::CloseHandle(pi.hThread); ::CloseHandle(pi.hProcess); ::CloseHandle(hWritePipe); ::CloseHandle(hReadPipe); return TRUE; }