安裝程序常需調用 PKZIP 等 DOS 工具解壓,但不想彈出黑框控制台,且需將 DOS 輸出重定向到自身界面文本框。匿名管道完美解決:父進程創建管道,子進程繼承句柄,標準輸出重定向至管道寫端,父進程從讀端獲取數據。
BOOL CreatePipe(
PHANDLE hReadPipe, // 讀端句柄輸出
PHANDLE hWritePipe, // 寫端句柄輸出
LPSECURITY_ATTRIBUTES lpPipeAttributes, // 安全屬性,控制句柄繼承
DWORD nSize // 緩衝區大小,0 為系統默認
);
SECURITY_ATTRIBUTES 關鍵字段:bInheritHandle = TRUE 使句柄可被子進程繼承。
關鍵參數配置:
bInheritHandles = TRUE:子進程繼承父進程可繼承句柄。STARTUPINFO 結構體定制:
hStdOutput = hWritePipe、hStdError = hWritePipe:標準輸出/錯誤重定向到管道寫端。wShowWindow = SW_HIDE:隱藏子進程窗口。dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW:啟用上述設置。GetStartupInfo 獲取默認值再修改,簡化初始化。創建進程後,**必須**在父進程中 CloseHandle(hWritePipe)。否則管道存在兩個寫端(父進程持有、子進程繼承),導致 ReadFile 永遠無法返回 0(EOF),陷入死循環。
dir /? 輸出到編輯框void CPipeDlg::OnButton1() {
SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, TRUE };
HANDLE hRead, hWrite;
if (!CreatePipe(&hRead, &hWrite, &sa, 0)) { AfxMessageBox(_T("CreatePipe失敗")); return; }
STARTUPINFO si; GetStartupInfo(&si);
si.hStdOutput = hWrite;
si.hStdError = hWrite;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
PROCESS_INFORMATION pi;
if (!CreateProcess(NULL, _T("cmd.exe /c dir /?"), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
AfxMessageBox(_T("CreateProcess失敗")); CloseHandle(hRead); CloseHandle(hWrite); return;
}
CloseHandle(hWrite); // 關鍵!
char buf[4096]; DWORD bytesRead;
while (ReadFile(hRead, buf, 4095, &bytesRead, NULL) && bytesRead > 0) {
buf[bytesRead] = '\0';
m_Edit1 += buf; // 假設為 CString 成員
UpdateData(FALSE);
Sleep(50);
}
CloseHandle(hRead);
CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
}
此模式廣泛適用於:編譯器輸出捕獲、命令行工具封裝、自動化腳本交互等場景。配合線程異步讀取可避免界面卡頓。