 さて、今回は実際に匿名パイプを作ってみます。
具体的作り方は前章を参照してください。
さて、今回は実際に匿名パイプを作ってみます。
具体的作り方は前章を参照してください。
// pipe01.c
#include <stdio.h>
#include <windows.h>
int WritePipe();
int MyCreateChildAndPipe();
HANDLE hWrite, hProcess;
int end;
int main()
{
    char ans[8];
    //子プロセスとパイプの作成
    MyCreateChildAndPipe();
    while (1) {
        printf("***** Menu *******\n");
        printf("1.パイプに書き込む\n");
        printf("0.終了\n");
        printf("******************\n");
        printf("--->");
        gets(ans);
        switch (ans[0]) {
            case '1':
                WritePipe();
                break;
            case '0':
                end = 1;
                WritePipe();
                break;
            default:
                printf("入力ミスです\n");
                break;
        }
        if (end == 1)
            break;
    }
    return 0;
}
プログラム開始とともに、MyCreateChildAndPipe関数で子プロセスと
匿名パイプを作ります。次にメニューを表示してユーザーに指示を促します。
ここでは、書き込みをするのか、終了するのかを選択します。
書き込みをする場合はWritePipe関数を呼んで書き込みをします。
さて、終了時にはendグローバル変数を1にして、WritePipe関数を呼びます。
これは、終了時にちょっとした細工をするためです。
int WritePipe()
{
    char szBuf[256];
    DWORD dwResult, dwError;
    if (end != 1) {
        printf("書き込みをしてください--->");
        gets(szBuf);
    } else {
        strcpy(szBuf, "end");
    }
    if (!WriteFile(hWrite, szBuf, sizeof(szBuf), &dwResult, NULL)) {
        dwError = GetLastError();
        if (dwError == ERROR_BROKEN_PIPE || dwError == ERROR_NO_DATA) {
            printf("パイプがありません\n");
        } else {
            printf("何らかのエラーです\n");
        }
        CloseHandle(hWrite);
        hWrite = NULL;
        CloseHandle(hProcess);
        hProcess = NULL;
        return -1;
    }
    return 0;
}
パイプに書き込みをする関数です。
グローバル変数のendが1の時は、パイプに"end"と書き込みます。
これが、終了の合図となります。
endが1でないときは、ユーザーに書き込みを促します。
WriteFile関数でパイプに書き込みを行います。
int MyCreateChildAndPipe()
{
    HANDLE hRead;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;
    if (!CreatePipe(&hRead, &hWrite, &sa, 0)) {
        printf("パイプの作成に失敗しました\n");
        return -1;
    }
    if (!DuplicateHandle(GetCurrentProcess(), //ソースプロセス
            hWrite, //duplicateするハンドル(オリジナルハンドル)
            GetCurrentProcess(), //ターゲットプロセス(行先)
            NULL, //複製ハンドルへのポインタ(コピーハンドル)
            0, //アクセス権
            FALSE, //子供がハンドルを継承するかどうか
            DUPLICATE_SAME_ACCESS)) { //オプション
                printf("DuplicateHandle Error\n");
                CloseHandle(hWrite);
                CloseHandle(hRead);
                hWrite = NULL;
                return -2;
    }
    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput = hRead;
    si.hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
    si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
    if (!CreateProcess(NULL, "pipe01child.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
        printf("CreateProcess Error\n");
        CloseHandle(hWrite);
        hWrite = NULL;
        return -3;
    } 
    hProcess = pi.hProcess;
    CloseHandle(pi.hThread);
    CloseHandle(hRead);
    return 0;
}
パイプと、子プロセスを作成する関数です。DuplicateHandle関数の意味がわかりにくいので、前章でもう一度復習しておいて ください。
さて、このプログラムのみではうまく動作しません。これとは、別に"pipe01child.exe" という名前のプログラムが必要です。
親プロセスから書き込みをした内容がパイプを通じてpipe01child.exeに送信されます。
次回は、pipe01child.exeを作ります。
Update Feb/09/2006 By Y.Kumei