HOWTO · Batch
Windowsバッチファイルでコマンドやexeの終了を待つ方法
通常のコマンドは順番に実行されます。別のバッチは CALL、START で起動したプログラムは START "" /WAIT を使い、終了コードを確認する方法を解説します。
このページの内容
バッチファイルでは、通常のコマンドや実行ファイルを直接実行すると、その処理が戻ってから次の行へ進みます。別のバッチファイルを呼び出す場合や、START でプログラムを起動する場合にだけ、専用の書き方が必要です。
| 状況 | 使う方法 |
|---|---|
| 通常のコマンドまたは実行ファイル | そのまま実行します。処理が戻ってから次の行が実行されます。 |
別の .bat または .cmd ファイル |
call child.cmd を使うと、子バッチの終了後に呼び出し元へ戻ります。 |
START で起動するプログラム |
start "" /wait program.exe を使うと、START が起動したプロセスの終了を待てます。 |
| 一定時間の待機またはユーザーの確認 | timeout または pause を使います。どちらもプロセスの完了は検出しません。 |
この記事では、それぞれの使い分けと、後続コマンドに上書きされる前に終了コードを保存する方法を説明します。
通常のコマンドやexeは直接実行する
コマンドや実行ファイルを単独の行で実行する場合、待機させるためだけに START を追加する必要はありません。最初のコマンドが戻ってから次のコマンドが実行されます。次の短いバッチファイルは、組み込みの echo コマンドでその順序を示します。
@echo off
echo [1] command start
echo [2] command returned
[1] command start
[2] command returned
実行ファイルを直接呼び出した場合も同じ順序になります。後続の処理で終了コードを使うなら、そのコマンドの直後に %ERRORLEVEL% を保存してください。後のコマンドによって値が変わることがあります。バッチファイルから保存済みの結果を返すには exit /b %rc% を使います。
別のバッチファイルはCALLで呼び出す
バッチファイルを名前だけで呼び出すと、制御がそのファイルへ移ります。呼び出し元もその後に処理を続ける必要がある場合は CALL を使います。たとえば、親バッチでは子バッチの戻り値を直後に保存できます。
parent.cmd:
@echo off
echo [parent] before call
call child.cmd input.txt
set "rc=%ERRORLEVEL%"
echo [parent] after call: exit code=%rc%
exit /b %rc%
child.cmd:
@echo off
echo [child] start
echo Processing "%~1"
exit /b
これは別々のファイルの例であり、実行済みのテストではありません。Windows のバッチでは、CALL を使うと子バッチの終了後に親へ制御が戻り、親は子の %ERRORLEVEL% を読み取れます。CALL を付けずに別の .bat または .cmd を実行すると、そのファイルへ制御が移り、親の後続行は実行されません。引数は子ファイル名の後ろに記述し、空白を含む引数は引用符で囲みます。コマンドの形式と戻り動作については、Microsoft の call リファレンスを参照してください。
STARTを使う場合は"" /WAITを付ける
別のプログラムを意図的に起動するときは START を使います。START が起動したプロセスの終了を待つには /WAIT を付けます。
start "" /wait "C:\Tools\My Program\worker.exe" --task import
set "rc=%ERRORLEVEL%"
echo worker exit code: %rc%
exit /b %rc%
これは Windows 固有コマンドの構文例です。外部実行ファイルはここに含まれていないため、実行結果を示すものではありません。空の "" はウィンドウタイトルです。START は最初の引用符付き引数をタイトルとして扱うため、引用符で囲んだ実行ファイルのパスより前に置く必要があります。/B は任意指定で、コンソールプログラムを現在のコマンドプロンプト内で実行しますが、待機は行いません。起動したプロセスの終了を待ってから戻るためのオプションは /WAIT です。
START /WAIT が待つのは、START 自身が起動したプロセスです。起動用プログラムが別の切り離された子プロセスを起動する場合、その子の処理まですべて完了したとは保証できません。この違いが重要な場合は、起動するプログラムのドキュメントを確認してください。オプションの一覧は Microsoft の start リファレンス、ほかの起動方法はバッチファイルでの START コマンドの使い方を参照してください。
TIMEOUTとPAUSEは完了待ちではない
経過時間を意図的に待つ場合は TIMEOUT を使いますが、別プロセスが完了した証明にはなりません。Microsoft の説明では、通常のキー入力でカウントダウンを中断させないには /NOBREAK を使い、TIMEOUT /T -1 はキーが押されるまで待つ方法です。PAUSE も対話的な入力を待ちます。Windows の TIMEOUT が受け付ける秒数は -1 から 99999 です。待ち時間は短すぎたり、不要に長くなったりする可能性があります。プロセスの完了を条件にする場合は CALL または START "" /WAIT を使ってください。
時間待ち専用のオプションや例については、バッチファイルで TIMEOUT を使う方法を参照してください。
トラブルシューティング
START /WAITの一般的な代わりとして、プロセス名を繰り返し確認するループを使わないでください。同じ名前のプロセスが複数存在する場合があり、起動用プログラムが切り離された子プロセスの完了前に戻ることもあります。- 対象コマンドの
%ERRORLEVEL%は直後に読み取ってください。echo、set、後続のコマンドによって値が変わることがあります。 - 自動処理の例に
cmd /kを加えないでください。これはコマンドプロンプトを開いたままにするため、スクリプトの完了を報告する方法には適しません。 - 管理者権限、ユーザー入力、ネットワーク接続、またはアプリ固有の完了通知が必要なプログラムでは、コマンドプロセスを待つだけで十分かどうかを、そのプログラムのドキュメントで確認してください。
まとめ
通常のコマンドは直接実行します。呼び出し元へ戻る必要がある別のバッチファイルには CALL を使い、START でプログラムを起動する場合は START "" /WAIT を使います。TIMEOUT と PAUSE はバッチファイルを一時停止しますが、プログラムの完了を判定するものではありません。