batファイルで多重起動(二重起動)を防止する

バッチファイルで多重起動(二重起動)を抑止するコードを探してみました。

bat 多重|二重 実行|起動 抑止|禁止|防ぐ|防止|できないように|させない - Google 検索

 方法として、大まかに2つあることがわかりました。

  • 方法1:バッチファイル自身を追記モードで開く。
  • 方法2:ロックファイルを使う。
  • 方法3:tsklistコマンドを使って実行している数をチェックする。

たが、方法3はチェックする前に複数起動されるとどれもチェックに引っかかり、行いたい処理が実行できない。よって方法1をベースにブラッシュアップしてみた。

@echo off
call :set_errorlevel 1
call :main %* 3>>"%~dpnx0"
if %ERRORLEVEL% neq 0 echo Error 1>&2
goto :eof
:set_errorlevel
exit /b %1
:main
echo main start
timeout 15
echo main end
exit /b 0

ちなみに方法1には、実行中はバッチファイル自体を変更できないという特徴があり、これもメリットでもあるが注意が必要である。不用意にエディタで開いているとすでに実行中であると判断されてしまいます。また、利用者にバッチファイル自体に書き込める権限があるのは危険です。
これを回避するには、方法2でかつ、バッチファイル自体を読み取り専用にします。コードは以下のようになります。テスト中はattrib行をコメントアウトして下さい。

@echo off
attrib +r %~dpnx0
call :set_errorlevel 1
call :main %* 3> "%TEMP%%~nx0.lock"
if %ERRORLEVEL% neq 0 echo Error 1>&2
del "%TEMP%%~nx0.lock" >nul 2>&1
goto :eof
:set_errorlevel
exit /b %1
:main
echo main start
timeout 15
echo main end
exit /b 0

 

参考にしたページ

Microsoft製品) コマンドプロンプト:バッチの多重起動を抑制する - YiaoWang

バッチファイルlを2重起動できないようにしたい - その他(プログラミング) 締切済み 【OKWAVE】

バッチファイルの二重起動を防止する。(その2) Windows Script Programming

バッチの二重起動防止 - ひらいて

以上です。

 

2017/9/1 追記

コードに問題があったので修正しました。ERRORLEVELをSETで変更していたところをサブルーチンを使った方法に変更、:mainサブルーチンの戻り値を0するところを追加、リダイレクト元のFDが0だとtimeoutコマンドがエラーになるので3に変更しました。FD3を使う場合はそれ以上に変更して下さい。