1

CreateProcess を使用して、Cygwin の bash.exe 経由で bash スクリプトを呼び出しています。スクリプトは正常に実行され、stdout と stderr をリダイレクトして自分のウィンドウ内に表示することさえできます。唯一の問題は、bash スクリプトの終了コードを取得できないように見えることです。

スクリプトを起動する方法は次のとおりです。

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

STARTUPINFO si; 
si.cb = sizeof (STARTUPINFO); 
si.lpReserved = NULL; 
si.lpDesktop = NULL;
si.lpTitle = NULL; 
si.dwX = 0; 
si.dwY = 0; 
si.dwXSize = 0; 
si.dwYSize = 0; 
si.dwXCountChars = 0; 
si.dwYCountChars = 0; 
si.dwFillAttribute = 0; 
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 
si.wShowWindow = SW_HIDE; 
si.cbReserved2 = 0; 
si.lpReserved2 = NULL; 
si.hStdOutput = hChildStdOut;
si.hStdInput  = NULL;
si.hStdError  = hChildStdErr;

CreateProcessW( NULL, 
    L"bash.exe script.sh file_to_process", 
    NULL, 
    NULL, 
    TRUE, 
    CREATE_NEW_CONSOLE, 
    NULL, 
    NULL, 
    &si, 
    &pi);

hChildProcess = pi.hProcess;

そして、これが私が終了コードを取得しようとしている方法です:

WaitForSingleObject(hChildProcess, 0);
DWORD exitCode = 999;
GetExitCodeProcess(hChildProcess, &exitCode);
DWORD lastError = GetLastError();

スクリプトによって返されるはずの終了コードに関係なく、 exitCode と lastError の両方が常にゼロのようです。

アップデート

cwgem が指摘したように、スクリプトはスクリプトexitを終了するために使用していました。returnそれらをすべて、スクリプトによって返される値ではない exitCode = 1 に変更しようとしました。少しグーグルで調べたところ$(exit n)、うまくいきましたが、スクリプトから最終的な終了コードしか取得できませんでした (現在、テスト用に 7 ですが、通常は 0 になります)。

たとえば、スクリプトに次のブロックがあります。

if [ `/cygdrive/c/cygwin/bin/find $root -name '*.xml' | grep -c .xml` -eq 0 ] ; then
echo No XMLs present in $root!
$(exit 2)
fi

このパスをテストすると、予想どおり stdout に「No XMLs」というメッセージが表示されますが、終了コードとして 2 が表示されません。代わりに 7 を取得します。これは、上で述べたように、スクリプトの最後の exit ステートメントです。

変数を作成して終了コードを保存し、最後にそれを返すことはできますが、実行してはいけないコードを実行する可能性があるため、それは正しい解決策とは思えません。

私はスクリプトの作成者でもメンテナーでもないことに注意してください。アプリケーションからスクリプトを実行するように求められただけです。

4

1 に答える 1

2

次の場合を除いて、bashは終了コードとして最後の実行コマンドの戻り値を返すため、スクリプトの実行フローを確認する必要があります。

  • を使用して強制的に終了しますexit [returncode]
  • set -eスクリプトの先頭。コマンドがゼロ以外の値で終了するとすぐに終了します。
于 2013-03-09T06:47:36.557 に答える