方法1
以下ページで紹介されている方法
call :main %* 4>>%0
goto :eof
:main
%*
はすべての引数を表すが、なくてもロックはかかる。
あったほうが良いのか不明。
4>>%0
は、上記ページで解説されているとおり。
1は標準出力で2は標準エラー出力で、4には割り当てがない(nul?)
%0はバッチ自体のパスを表すので、4>>%0
と書くと、nul>>バッチファイル自体
となって、:main呼び出しの間、ロックがかかるようになる
(4ではなく3でも良さそう)
で、例えば以下バッチを作成して実行して動作を見る
call :main %* 4>>%0
goto :eof
:main
timeout 1000
バッチを実行すると1000秒待機になる。
その状態でさらにバッチを起動すると、エラーメッセージ/ダイアログが表示されて多重実行が防止される
ただし、この方法だと、バッチ実行中、バッチの編集もできない。
なお、単にバッチをエディタで開いた状態からは、バッチ起動はできた
(なのでエディタで開いてることがバッチ失敗の原因になることはない)
なので、バッチ実行もしながらエディタで編集したい場合はこの方法は向かない。
バッチを実行しながらエディタで編集したりしないとか、バッチを都度止めてから編集する場合はこの方法でも良い
方法2
以下ページで紹介されている方法
上記が自分の環境では動かなかったのでちょっと修正させていただいて、さらにバッチファイル名を自動取得にしたものが以下
@REM //多重起動防止
for /f %%b in ('"tasklist /FI "WINDOWTITLE eq %~nx0" | find /C /I "cmd.exe""') do set process=%%b
IF %process% GEQ 1 (
echo The program is already running. Terminate the program.
timeout /t 5 >nul
exit
)
title %~nx0
ミソは、まずTITLEがバッチ名になってるcmd.exeプロセスがあればexitして、なければtitleを設定するところ。
titleを先に設定すると、自分のバッチをtasklist~ findで拾っちゃうので、まず自分以外で同じtitleのバッチがないか確認してからtitleを設定する。
こちらの方法は、自分のバッチ名がtitleに設定されたcmd.exeプロセスの多重起動を見てるので、バッチを実行しながらエディタで編集できる。
個人的にはこっちが好き
他参考ページ
こちらにまとまってました
たしかにロックファイルもありますね
(ロックファイルだと、バッチが半端に終わった時に残ってしまった場合の想定が必要そうですね)