WindowsのERRORLEVELにハマった

 以下のようなコードを含んだバッチファイルが期待どおりに動かなくて悩んだ。

DIR /0 2>NUL

IF %ERRORLEVEL% NEQ 0 (ECHO Error) ELSE (ECHO Ok)

 DIR /0は必ずエラーになりERRORLEVELが1になり"Error"と出力されるはずであるが、テストしていたコマンドプロンプトでこのバッチファイルを実行するとはなぜか必ず"Ok"と出力されてしまう。

色々ネットを徘徊するとERRORLEVELという環境変数が上書きで設定されていて、本来のERRORLEVELが見えなくなっていることがわかった。コンソールで色々コマンドをテストしていたときに"SET ERRORLEVEL=0"としていたので、それがずっとが悪さをしていた。

テストしていたコマンドプロンプトで"SET ERRORLEVEL="してから、バッチファイルを実行したら正常に動いた。

SET コマンドのヘルプ より

コマンド拡張機能が有効な場合、SET によって表示される変数の一覧には
現れないいくつかの動的な環境変数があります。
これらの変数の値は、変数の値が展開されるときに
動的に計算されます。
ユーザーがこれらの名前の変数を明示的に定義する場合、
その定義は下記の動的な定義を無効にします。

%CD% - 現在のディレクトリ文字列に展開します。

%DATE% - DATE コマンドと同じフォーマットで現在の日付に展開します。

%TIME% - TIME コマンドと同じフォーマットで現在の時刻に展開します。

%RANDOM% - 0 から 32767 の間の任意の 10 進数に展開します。

%ERRORLEVEL% - 現在の ERRORLEVEL の値に展開します。

%CMDEXTVERSION% - 現在のコマンド プロセッサ拡張機能のバージョン番号に
展開します。

%CMDCMDLINE% - コマンド プロセッサを起動したオリジナル コマンド ライン
に展開します。

%HIGHESTNUMANODENUMBER%
- このコンピューター上の最大の NUMA ノード番号に展開します。

Windowsのバッチファイルやコマンドプロンプトでは、これらの特殊な環境変数はSETで変更してはいけない。

過去に書いた記事(batファイルで多重起動(二重起動)を防止する )のコードも修正しました。

 

参考にしたページ

終了コード errorlevel の考え方について -こんばんは。OSはWindowsXP - その他(プログラミング・Web制作) | 教えて!goo

ERRORLEVELは、一般の環境変数と異なり、SET で値を代入してはいけません。(参考: set /? で表示される最終ページ)
SET を使うと一般の環境変数となってしまい、次にSETするまで値は変わりません。コマンドの実行結果と切り離されると言うことです。

ERRORLEVELについてのメモ (1) - とあるソフトウェア開発者のブログ

ERRORLEVELについてのメモ (2) - とあるソフトウェア開発者のブログ