ERRORLEVELについてのメモ (2)

前回の続きです。(前回: id:simply-k:20100812:1281653517)

ERRORLEVELが設定されない場合

説明

コマンドやバッチスクリプトを実行しても、ERRORLEVELが設定されない場合がある。

  • ERRORLEVELを設定しないコマンドが存在する。(echo、pause、remなど) *1
  • callしたバッチスクリプトが、ERRORLEVELを変更するような処理をせず、さらに終了コードを指定せずに終了した場合
  • callしたバッチスクリプトが、callされた段階でのERRORLEVELを終了コードとして指定する場合
動作確認

テスト用のバッチファイル

@echo off

rem テスト1 (echo)
call :set_errorlevel 10
echo [test-1-1] %ERRORLEVEL%
echo [test-1-2] %ERRORLEVEL%

rem テスト2 (pause)
call :set_errorlevel 20
echo [test-2-1] %ERRORLEVEL%
pause < NUL > NUL
echo [test-2-2] %ERRORLEVEL%

rem テスト3 (rem)
call :set_errorlevel 30
echo [test-3-1] %ERRORLEVEL%
rem コメント
echo [test-3-2] %ERRORLEVEL%

rem テスト4 (バッチスクリプト1)
call :set_errorlevel 40
echo [test-4-1] %ERRORLEVEL%
call :keep_errorlevel_1
echo [test-4-2] %ERRORLEVEL%

rem テスト5 (バッチスクリプト2)
call :set_errorlevel 50
echo [test-5-1] %ERRORLEVEL%
call :keep_errorlevel_2
echo [test-5-2] %ERRORLEVEL%

pause
exit /b 0

rem ERRORLEVELを設定するサブルーチン
:set_errorlevel
exit /b %1

rem ERRORLEVELを変更しないサブルーチン1
:keep_errorlevel_1
pause < NUL > NUL
exit /b

rem ERRORLEVELを変更しないサブルーチン2
:keep_errorlevel_2
set ERROR_CODE=%ERRORLEVEL%
copy > NUL
exit /b %ERROR_CODE%


実行結果

[test-1-1] 10
[test-1-2] 10
[test-2-1] 20
[test-2-2] 20
[test-3-1] 30
[test-3-2] 30
[test-4-1] 40
[test-4-2] 40
[test-5-1] 50
[test-5-2] 50

ERRORLEVELと遅延展開

説明

if文やfor文の中でERRORLEVELが設定された場合、そのif文やfor文の中で「%ERRORLEVEL%」としても、最新の値を取得できません。遅延展開を有効にした上で、「!ERRORLEVEL!」を使う必要があります。*2 ただし、「if ERRORLEVEL n」を使った場合は、遅延展開の有効・無効に関わらず、常に最新のERRORLEVELで判定されるようです。

動作確認

テスト用のバッチファイル

@echo off

rem 初期状態
echo [default] %ERRORLEVEL%

rem テスト (遅延展開あり)
setlocal EnableDelayedExpansion
if 1 == 1 (
    call :set_errorlevel 1
    echo [test-1-1] %ERRORLEVEL%
    echo [test-1-2] !ERRORLEVEL!
    
    if ERRORLEVEL 1 (
        echo [test-1-3] 1以上
    ) else (
        echo [test-1-3] 1未満
    )
)

rem テスト (遅延展開なし)
setlocal DisableDelayedExpansion
if 1 == 1 (
    call :set_errorlevel 1
    echo [test-2-1] %ERRORLEVEL%
    echo [test-2-2] !ERRORLEVEL!
    
    if ERRORLEVEL 1 (
        echo [test-2-3] 1以上
    ) else (
        echo [test-2-3] 1未満
    )
)

pause
exit /b 0

rem ERRORLEVELを設定するサブルーチン
:set_errorlevel
exit /b %1


実行結果

[default] 0
[test-1-1] 0
[test-1-2] 1
[test-1-3] 1以上
[test-2-1] 0
[test-2-2] !ERRORLEVEL!
[test-2-3] 1以上

ERRORLEVELの範囲

説明

ERRORLEVELに設定できる値の範囲は、おそらくWindowsのバージョンによって違うと思います。手元の環境(Windows XP SP3)では、-(231) 〜 231-1でした。*3 「exit /b」で範囲外の値を設定しようとすると、自動的に範囲内の値に変換されるようです。

動作確認

テスト用のバッチファイル

@echo off

rem 2^31 - 1 (最大)
call :set_errorlevel 2147483647
echo [test-1] %ERRORLEVEL%

rem 2^31 (最大 + 1)
call :set_errorlevel 2147483648
echo [test-2] %ERRORLEVEL%

rem -(2^31) (最小)
call :set_errorlevel -2147483648
echo [test-3] %ERRORLEVEL%

rem -(2^31 + 1)  (最小 - 1)
call :set_errorlevel -2147483649
echo [test-4] %ERRORLEVEL%

pause
exit /b 0

rem ERRORLEVELを設定するサブルーチン
:set_errorlevel
exit /b %1


実行結果

[test-1] 2147483647
[test-2] -2147483648
[test-3] -2147483648
[test-4] 2147483647

ERRORLEVELについてのメモは、これで終わりです。(前回: id:simply-k:20100812:1281653517)

*1:ヘルプに書いてあったわけではないのですが、ERRORLEVELを設定することは、たぶんありません。

*2:通常の環境変数と同じです。

*3:符号付き32ビット整数として扱われるようです。