首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 匿名管道技術實戰:隱藏控制台捕獲 DOS 程序輸出

     編輯:VC 教學

場景痛點

安裝程序常需調用 PKZIP 等 DOS 工具解壓,但不想彈出黑框控制台,且需將 DOS 輸出重定向到自身界面文本框。匿名管道完美解決:父進程創建管道,子進程繼承句柄,標準輸出重定向至管道寫端,父進程從讀端獲取數據。

核心 API 與結構體

1. CreatePipe 創建管道

BOOL CreatePipe(
    PHANDLE hReadPipe,      // 讀端句柄輸出
    PHANDLE hWritePipe,     // 寫端句柄輸出
    LPSECURITY_ATTRIBUTES lpPipeAttributes, // 安全屬性,控制句柄繼承
    DWORD nSize             // 緩衝區大小,0 為系統默認
);

SECURITY_ATTRIBUTES 關鍵字段:bInheritHandle = TRUE 使句柄可被子進程繼承。

2. CreateProcess 創建子進程

關鍵參數配置:

  • bInheritHandles = TRUE:子進程繼承父進程可繼承句柄。
  • STARTUPINFO 結構體定制:
    • hStdOutput = hWritePipe、hStdError = hWritePipe:標準輸出/錯誤重定向到管道寫端。
    • wShowWindow = SW_HIDE:隱藏子進程窗口。
    • dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW:啟用上述設置。
  • 調用 GetStartupInfo 獲取默認值再修改,簡化初始化。

3. 關鍵細節:關閉父進程寫端

創建進程後,**必須**在父進程中 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);
}

擴展應用

此模式廣泛適用於:編譯器輸出捕獲、命令行工具封裝、自動化腳本交互等場景。配合線程異步讀取可避免界面卡頓。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved