調べものしていたら、たまたまこんな記事を見つけた。
なかなか終わらない処理を我慢できずにkillするbatファイル
内容としては、立ち上げたプロセスを tasklist で検索して、無かったら終了、有ったらループと言う、まぁ普通そういう風に作るよね、という内容だったんですが、記事の中に書かれていた
dosにだっていろいろなコマンドがあるのです!
という一言に触発され、ドマイナーなコマンド使ってループ処理を入れずに作ってみました(笑)
サンプルとして、メモ帳(notepad.exe)を起動し、一定時間内にメモ帳を終了すれば正常終了、一定時間過ぎたら起動したメモ帳を強制終了するという内容で作ってみた。
@echo off setlocal start "WaitProc" /min cmd.exe /c "start /wait notepad.exe && waitfor /s %COMPUTERNAME% /si hoge" for /f "usebackq tokens=2" %%i in (`tasklist /v ^| findstr "WaitProc"`) do set WAITPID=%%i waitfor /t 20 hoge if %ERRORLEVEL% equ 0 ( echo 正常終了 exit /b 0 ) else ( echo タイムアウト taskkill /f /t /pid %WAITPID% exit /b 1 )
まず4行目でメモ帳が終了するまで待機するというプロセスをバックグラウンドで起動します。ややこしい(笑)
で、キモはメモ帳の後に実行する waitfor という確か Vista 辺りから追加されているコマンドなんですが、詳細は後述。
5行目で、4行目で起動したプロセスの PID を変数 WATIPID に設定。4行目最初の start で設定した WaitProc というウインドウタイトルを頼りにプロセスを特定します。この文字列は他のプロセスと被らなければなんでも良い。
7行目、キモの waitfor 。 hoge というシグナルを20秒待つ設定。”シグナル”ってなんじゃらホイ?って感じですが、4行目の waitfor のオプション /si で指定した文字列がシグナル。4行目で、メモ帳が終了すれば送られてくる、という寸法。
waitfor はシグナルが送られて来れば正常終了で0を返し、タイムアウトすれば1を返すので、 errorlevel で条件分岐してプロセスを殺せば良い。
ちなみに、4行目の waitfor では、オプション /s で明示的に自分にシグナルを送っていますが、勿論リモートホストにも送れます。しかも、送信先を指定しなければブロードキャストするので、複数のマシンで同じシグナル待ち受けさせておけば、いっせーのせで処理継続させたりすることもできちゃいます。使い道思いつかねー(笑)
※但し、リモートに対しては認証が掛るので要注意。詳細は waitfor /? 見てね。