◆ 名前なしパイプのサンプルプログラム
//------------------------------------------------------------------------------
// module name: pipe.cpp
// desc: 名前なしパイプのサンプルプログラム
//
//   参考URL <http://support.microsoft.com/support/kb/articles/q190/3/51.asp>
//------------------------------------------------------------------------------
#include <windows.h>
#include <conio.h>   // getch()
#include <iostream>  // std::cout, std::endl

// 子プロセスの標準出力を読み取る
void read_child_stdout(HANDLE h_stdout_r);

//------------------------------------------------------------------------------
// name: main()
// desc: 子プロセス c:\aaa\bbb\ccc\test.exe の標準出力を、名前なしパイプを用いて
//       親プロセスにリダイレクトする
//------------------------------------------------------------------------------
int main()
{
    char* curr_dir = "c:\\aaa\\bbb\\ccc";           // 子プロセスの実行時カレントディレクトリ
    char* cl = "c:\\aaa\\bbb\\ccc\\test";           // コマンドライン

    // 標準出力パイプ
    HANDLE h_stdout_r, h_stdout_r_tmp;              // 標準出力を読み込むパイプ端 (親側)
    HANDLE h_stdout_w;                              // 標準出力へ書き込むパイプ端 (子側)
    // 標準入力パイプ
    HANDLE h_stdin_w, h_stdin_w_tmp;                // 標準入力へ書き込むパイプ端 (親側)
    HANDLE h_stdin_r;                               // 標準入力を読み込むパイプ端 (子側)
    // 標準エラー出力パイプ
    HANDLE h_stderr_w;                              // 標準エラー出力へ書き込むパイプ端 (子側)

    HANDLE h_parent_process = GetCurrentProcess();  // 親プロセス(カレントプロセス)のハンドル
    HANDLE h_child_process;                         // 子プロセスのハンドル

    // Setup SECURITY_ATTRIBUTES structure
    SECURITY_ATTRIBUTES sa;
    sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle       = TRUE;

    // ----------------( h_stdout_w )----------------
    // Create the child output pipe.
    CreatePipe(&h_stdout_r_tmp, &h_stdout_w, &sa, 0);

    // ----------------( h_stderr_w )----------------
    // Create a duplicate of the output write handle for the std error
    // write handle. This is necessary in case the child application
    // closes one of its std output handles.
    DuplicateHandle(h_parent_process, h_stdout_w, h_parent_process, &h_stderr_w, 0, TRUE, DUPLICATE_SAME_ACCESS);

    // ----------------( h_stdin_r )----------------
    // Create the child input pipe.
    CreatePipe(&h_stdin_r, &h_stdin_w_tmp, &sa, 0);

    // ----------------( h_stdout_r, h_stdin_w )----------------
    // Create new output read handle and the input write handles. Set
    // the Properties to FALSE. Otherwise, the child inherits the
    // properties and, as a result, non-closeable handles to the pipes
    // are created.                                                                      ↓ Uninheritable
    DuplicateHandle(h_parent_process, h_stdout_r_tmp, h_parent_process, &h_stdout_r, 0, FALSE, DUPLICATE_SAME_ACCESS);
    DuplicateHandle(h_parent_process, h_stdin_w_tmp,  h_parent_process, &h_stdin_w,  0, FALSE, DUPLICATE_SAME_ACCESS);

    // Close inheritable copies of the handles you do not want to be inherited.
    CloseHandle(h_stdout_r_tmp);
    CloseHandle(h_stdin_w_tmp);

    // Setup the STARTUPINFO structure.
    STARTUPINFO si;
    ZeroMemory(&si,sizeof(STARTUPINFO));
    si.cb          = sizeof(STARTUPINFO);
    si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    si.hStdOutput  = h_stdout_w;
    si.hStdInput   = h_stdin_r;
    si.hStdError   = h_stderr_w;

    // 子プロセスを起動する
    PROCESS_INFORMATION pi;
    CreateProcess(NULL, cl, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, curr_dir, &si, &pi);

    // Set child process handle to cause threads to exit.
    h_child_process = pi.hProcess;

    // Close any unnecessary handles.
    CloseHandle(pi.hThread);

    // Close pipe handles (do not continue to modify the parent).
    // You need to make sure that no handles to the write end of the
    // output pipe are maintained in this process or else the pipe will
    // not close when the child process exits and the ReadFile will hang.
    CloseHandle(h_stdout_w);
    CloseHandle(h_stdin_r);
    CloseHandle(h_stderr_w);

    // 子プロセスの標準出力を読み取る
    read_child_stdout(h_stdout_r);

    // 後始末 (パイプと子プロセスを閉じる)
    CloseHandle(h_stdout_r);
    CloseHandle(h_stdin_w);
    CloseHandle(h_child_process);

    std::cout << "\n\n\nHit any key to exit." << std::endl;
    getch();
    return 0;
}

//------------------------------------------------------------------------------
// name: read_child_stdout()
// desc: 子プロセスの標準出力を読み取る
//------------------------------------------------------------------------------
void read_child_stdout(HANDLE h_stdout_r)
{
    char buf[256]; // 読み取りバッファ
    DWORD bytes;   // 実際に読み取ったデータのサイズ

    while (ReadFile(h_stdout_r, buf, sizeof(buf), &bytes, NULL)) {
        int len = bytes / sizeof(char);
        buf[len] = '\0';
        std::cout << buf;
    }

    std::cout << std::endl;
}