2016-05-25 22 views
4

更新質問:私はプロセスを作成し、コンパイルするプログラムを入手することができました。しかし、私は新しい問題にぶつかります。ソースプログラムをフィルタプログラムにパイプするとき。シンクプログラムの入力にはフィードがないようです。エラーメッセージはありません。私はまた、Windowsのcmdでパイプ演算子を使って私のスタンドアローンプログラムをすべてテストしました。プロセスと匿名パイプの作成

私はこの小さなプロジェクトを匿名パイプについて学び、プロセスを作成しようとしています。 Source、Filter、Sinkという3つの小さなスタンドアロンプ​​ログラムを作成しました。これら3つはすでにコンパイルされており、うまく動作しています。ここでは、3つのスタンドアローンプログラムについて説明します。

ソース:コマンドラインからソーステキストファイルfilenameを取得し、ファイルを開き、一度に1文字ずつファイルを読み込んで標準出力(stdout)に直接コピーします。ファイルがコピーされると、Sourceは終了します(開いているファイルハンドルをすべて閉じます)。

フィルタプログラムは、ファイル名のコマンドラインパラメータを使用しません。代わりに、Filterは標準入力(stdin)からテキストファイルを読み込み、すべての大文字を小文字に変換した入力のコピーを標準出力(stdout)に書き込みます。フィルターは、入力データが終了するまで、1文字を読み取り、変換し、出力し、ループするように特別に設計する必要があります。

シンクプログラムは、コマンドラインから宛先テキストファイルのファイル名を取得し、書き込み用にファイルを開き、標準入力ファイル(stdin)から一度に1文字ずつ読み込み、各受信文字を宛先シンクファイルに直接書き込みます。

次の2つのパイプを作成し、指定された同時実行とデータフローを実行するように構成された入力と出力を持つ3つの独立した子を生成するメインドライバプログラムを別々に駆動しています。

: - >ソース - > PIPE1 - >フィルタ - > PIPE2 - - >シンク>

destfileドライバプログラムは、2つのコマンドラインパラメータを必要とします

  • はSRCFILE:このような何かSRCFILEは、既存のデータのテキストファイルです
    • C:\> Driver.exe srcfile destfile

    、 destfileはシンクアプリケーションによって作成される新しいデスティネーションファイルのファイル名です。

    ここに私のドライバプログラムのコードがあります。それはまだ終わっていない。しかし、私は、ソースプログラムのプロセスを作成しようとするときにちょっとした問題に遭遇しました。

    更新されたコードは:

    #include <windows.h> 
    #include <WinBase.h> 
    #include <stdio.h> 
    
    
    #define DELAY_A_WHILE() {volatile long j; for(j = 1; j< 10000; j++) ; } 
    
    int main(int argc, char *argv[]) 
    { 
        HANDLE hPipeRead, hPipeWrite, hPipeRead2, hPipeWrite2; 
        STARTUPINFO StartupInfoSource; 
        STARTUPINFO StartupInfoFilter; 
        STARTUPINFO StartupInfoSink; 
        PROCESS_INFORMATION ProcInfoSource; 
        PROCESS_INFORMATION ProcInfoFilter; 
        PROCESS_INFORMATION ProcInfoSink; 
        SECURITY_ATTRIBUTES PipeAttributes; 
        SECURITY_ATTRIBUTES PipeAttributes2; 
        char cmdline[200]; 
    
        PipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); 
        PipeAttributes.lpSecurityDescriptor = NULL;  //ignore 
        PipeAttributes.bInheritHandle = TRUE;   //child can inherit 
    
        //Create first pipe 
        if (!CreatePipe(&hPipeRead, &hPipeWrite, &PipeAttributes, 0)) { 
         fprintf(stderr, "Error creating pipe: %d\n", GetLastError()); 
         exit(1); 
        } 
    
        sprintf_s(cmdline, 200, "Source.exe %s", argv[1]); 
        printf("Create process: %s\n", cmdline); 
    
        GetStartupInfo(&StartupInfoSource); 
        StartupInfoSource.dwFlags = StartupInfoSource.dwFlags | STARTF_USESTDHANDLES; 
    
    
        //Mapping 
        StartupInfoSource.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 
        StartupInfoSource.hStdOutput = hPipeWrite; 
        StartupInfoSource.hStdError = GetStdHandle(STD_ERROR_HANDLE); 
    
        if (!CreateProcess(
         NULL, cmdline, NULL, NULL, 
         TRUE, 
         CREATE_NEW_CONSOLE, NULL, NULL, 
         &StartupInfoSource, 
         &ProcInfoSource)) 
        { 
         fprintf(stderr, "Error creating child process: %d",GetLastError()); 
         exit(1); 
        } 
    
        CloseHandle(hPipeWrite); 
        CloseHandle(ProcInfoSource.hProcess); 
        CloseHandle(ProcInfoSource.hThread); 
    
        PipeAttributes2.nLength = sizeof(SECURITY_ATTRIBUTES); 
        PipeAttributes2.lpSecurityDescriptor = NULL;  //ignore 
        PipeAttributes2.bInheritHandle = TRUE;   //child can inherit 
        //Create Second Pipe 
        if (!CreatePipe(&hPipeRead2, &hPipeWrite2, &PipeAttributes2, 0)) { 
         fprintf(stderr, "Error creating pipe: %d\n", GetLastError()); 
         exit(1); 
        } 
    
        GetStartupInfo(&StartupInfoFilter); 
        StartupInfoFilter.dwFlags = StartupInfoFilter.dwFlags | STARTF_USESTDHANDLES; 
    
        //Mapping 
        StartupInfoFilter.hStdInput = hPipeRead; 
        StartupInfoFilter.hStdOutput = hPipeWrite2; 
        StartupInfoFilter.hStdError = GetStdHandle(STD_ERROR_HANDLE); 
    
        sprintf_s(cmdline, 200, "Filter.exe"); 
        printf("Create process: %s\n", cmdline); 
    
        //Filter 
        GetStartupInfo(&StartupInfoFilter); 
        if (!CreateProcess(
         NULL, cmdline, NULL, NULL, 
         TRUE, 
         CREATE_NEW_CONSOLE, NULL, NULL, 
         &StartupInfoFilter, 
         &ProcInfoFilter)) 
        { 
         fprintf(stderr, "Error creating child process: %d", GetLastError()); 
         exit(1); 
        } 
    // int exitStatus; 
        // GetExitCodeProcess(ProcInfoFilter.hProcess, &exitStatus); 
        CloseHandle(hPipeRead); 
        CloseHandle(hPipeWrite2); 
        CloseHandle(ProcInfoFilter.hProcess); 
        CloseHandle(ProcInfoFilter.hThread); 
    
    
        GetStartupInfo(&StartupInfoSink); 
        StartupInfoSink.dwFlags = StartupInfoSink.dwFlags | STARTF_USESTDHANDLES; 
    
    
    
        //Mapping 
        StartupInfoSink.hStdInput = hPipeRead2; 
        StartupInfoSink.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 
        StartupInfoSink.hStdError = GetStdHandle(STD_ERROR_HANDLE); 
    
        sprintf_s(cmdline, 200, "Sink.exe %s", argv[2]); 
        printf("Create process: %s\n", cmdline); 
    
        GetStartupInfo(&StartupInfoSink); 
        if (!CreateProcess(
         NULL, cmdline, NULL, NULL, 
         TRUE, 
         CREATE_NEW_CONSOLE, NULL, NULL, 
         &StartupInfoSink, 
         &ProcInfoSink)) 
        { 
         fprintf(stderr, "Error creating child process: %d", GetLastError()); 
         exit(1); 
        } 
    
        CloseHandle(hPipeRead2); 
        CloseHandle(ProcInfoSink.hProcess); 
        CloseHandle(ProcInfoSink.hThread); 
    
    
        return 0; 
    } 
    

    プログラムは罰金コンパイルします。ただし、プロセスを作成しようとすると、常に失敗して終了します。 cmdlineの値は、 "Source.exe test.txt"です。これは、スタンドアロンソースプログラムを実行するために使用したものです。誰かが私のCreateProcessが失敗する理由を説明できますか?それは間違ったパラメータを解析するためですか?

+0

あなたは 'CreateProcess'が失敗すると言っていますか?次に、GetLastErrorによって返されたエラーコードを調べる必要があります。ところで、呼び出しプロセスの 'STARTUPINFO'を渡すのは正しいですか? stdinとstdoutにハンドルを渡すのですか? –

+0

私はデバッグしようとすると、プログラムの作成と終了に失敗したときにエラーを出力するif(!CreateProcess())の中で、プログラムは常にそのチャンクを実行します。 –

答えて

2

私がここで見ることができる唯一の問題は、Source.exeアプリケーションがDriver.exeがあるのと同じディレクトリにない可能性があることです。あなたのコードを試してみましたが、それはCreateProcessが失敗した唯一のケースでした。

+0

私のsource.exeは、Driver.cファイルと同じフォルダにあります。それはそれが正しい場所ですか? –

+0

あなたのバイナリは、通常、あなたが使用しているビルド設定に応じて、リリースまたはデバッグフォルダに置かれます。 「ソリューション用のディレクトリを作成する」オプションをオンにしてプロジェクトを作成した場合は、2つの異なるリリースと2つの異なるデバッグフォルダが表示されます。ディレクトリ構造の上位層にあるものが必要です。とにかく、driver.exeファイルの正確な場所を見つけて、このフォルダにsource.exeを入れてみてください。 –

+0

私はすでにやりました。それと同じことがまだあります。 –

-1

私は理由を理解しています。私のプロジェクトのプロパティはUnicode文字セットを使用していました。マルチバイト文字セットに切り替えると正常に動作します。

+0

それは明らかにタイヤではないです。問題のコードはコンパイルされませんでした。これは、偽のコードを紛失した場合に起こります。恥を知れ。マルチバイトに切り替えるのは間違った方法です。それは2016年です。既にUnicodeを使用してください! –

+0

質問の中のコードがコンパイルされています。私は、Unicode文字セットがWin32コンソールでサポートされておらず、適切に表示されないため、避けるのが最善であると述べたstackoverflowに関する他のいくつかの質問を調べました。だから、あなたはUnicode文字セットでそれを行うという提案はありますか? –

+0

そのコードがコンパイルされると、Unicodeは定義されません。 UnicodeはWindowsコンソールでサポートされています。 –

関連する問題