8

アプリを起動して stdout や stderr 経由で出力をキャプチャするにはどうすればよいですか?

自動ビルド システムを作成しており、分析のために出力を取得する必要があります。成功した場合はファイルを autobuild/revNumber/ に移動できるように、svn リポジトリを更新してリビジョン番号を取得したいと思います。また、make を使用してビルドし、コンパイル テキストをサーバーにアップロードして、失敗したビルドの警告とエラーを全員が確認できるようにしたいと考えています。

関数が見つかりませんが、MSDNsystem()で関数を見つけました。CreateProcess()必要なものを起動できますが、stderr と stdout をキャプチャする方法がわかりません。ブレークポイントを設定してアプリを終了したままにしない限り、プロセスが個別に起動することに気付きました。これにより、アプリのコンソール ウィンドウにすべてのテキストが保持されます。また、すべてのプロセスが完了するまで待ってから、生成されたデータをスキャンして、必要な追加操作を実行したいと考えています。これを行うにはどうすればよいですか?

4

3 に答える 3

11

実際のシェル (つまり、海のシェルではありません。つまり、C シェルまたはその派生物ではありません) では、次のようになります。

program arg1 arg2 >/tmp/log.file 2>&1

これにより、指定された引数でプログラムが実行され、stdout が /tmp/log.file にリダイレクトされます。表記 (ヒエログリフ) ' 2>&1' は最後に stderr (ファイル記述子 2) を stdout (ファイル記述子 1) と同じ場所に送信します。操作の順序が重要であることに注意してください。それらを逆にすると、標準エラーは標準出力が出力されていた場所に出力され、標準出力 (ただし標準エラーではありません) はファイルにリダイレクトされます。

表示されているファイル名の選択は、多くの理由で最悪です。ユーザーがディレクトリを選択できるようにする必要があり、おそらくファイル名にプロセス ID またはタイムスタンプを含める必要があります。

LOG=${TMPDIR:-/tmp}/log.$$.$(date +%Y%m%d-%H%M%S)
program arg1 arg2 >$LOG 2>&1

C++ では、system()(C から継承された) 関数を使用してプロセスを実行できます。C++ プログラムでファイル名を知る必要がある場合 (もっともらしい)、プログラムで名前を生成し (strftime()あなたの友達です)、そのファイル名でコマンド文字列を作成します。(厳密には、プロセス ID を取得getenv()するために $TMPDIR と POSIX 関数も取得する必要がありgetpid()ます。その後、2 行のシェル スクリプトをシミュレートできます (使用される PID は、起動されたシェルではなく、C++ プログラムのものになります)。

代わりに POSIXpopen()関数を使用できます。2>&1コマンドの標準エラーを標準出力と同じ場所に送信するには、作成するコマンド文字列に' ' 表記を含める必要がありますが、一時ファイルは必要ありません。

FILE *pp = popen("program arg1 arg2 2>&1", "r");

その後、ファイル ストリームを読み取ることができます。C ファイル ストリームを C++ istream にマップするクリーンな方法があるかどうかはわかりません。ありそうです。

于 2008-11-19T00:42:34.150 に答える
4

hStdInput、hStdOutput、および hStdError を持つ STARTUP_INFO 構造体を埋める必要があります。CreateProcess を実行するときは、ハンドルを継承することを忘れないでください。

/* Assume you open a file handle or pipe called myoutput */
STARTUP_INFO si_startinfo;
ZeroMemory(&si_startinfo, sizeof(STARTUP_INFO));
si_startinfo.cb = sizeof(STARTUP_INFO);
si_startinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si_startinfo.hStdOutput = myoutput;
si_startinfo.hStdError = myoutput;
si_startifno.dwFlags != STARTF_USEHANDLES;

PROCESS_INFORMATION pi_procinfo;
ZeroMemory(&pi_procinfo, sizeof(PROCESS_INFORMATION);

CreateProcess(NULL, cmdline, NULL, NULL, true, 0, NULL, pathname, &si_startinfo, &pi_procinfo);

エラー処理の側面については示していませんが、それを行う必要があります。ハンドルを継承するために、5 番目の引数は true に設定されます。他の人がパイプの作成方法を説明しているので、ここでは繰り返しません。

于 2008-11-19T00:56:59.673 に答える
0

MicrosoftのCRTとMSDNライブラリには、システム関数と_popen関数が含まれています。

于 2008-11-19T01:00:21.417 に答える