2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

windows batchでのエラーハンドリング

Posted at

概要

Windowsのbatchではtrapのようなコマンドや、set -eのようなエラーで即終了するような機構がないためエラーハンドリングする場合は%ERRORLEVEL%を全コマンド実行後にチェックする必要がある。
しかし、それだとエラーチェックの行が多くなりすぎるため読みづらいコードになってしまう。
その点を改善できる方法を考えてみる。

単純にエラーコードを返す

結論から言うと、以下のようにすることでエラーコードを呼び出し側に返すことができる。

some_command || exit /b !ERRORLEVEL!

これはサブルーチンのcallに対しても使えるため、

call :sub || exit /b !ERRORLEVEL!
exit /b

:sub
    some_commandA || exit /b !ERRORLEVEL!
    some_commandB || exit /b !ERRORLEVEL!
    some_commandC || exit /b !ERRORLEVEL!
exit /b

のように使うことができる。

エラー表示をする

batchにする以上何度も実行されると思うが、呼び出しをする度にコマンドプロンプトなどで%ERRORLEVEL%を確認するのは不毛なのでエラー表示もbatchにしたい。

some_command || call :onerror || exit /b !ERRORLEVEL!
exit /b

:onerror
echo エラー発生[%ERRORLEVEL%]
exit /b

上記の処理を見るとわかる通りcallechoでは%ERRORLEVEL%の書き換えが起こらないのでエラーハンドラをcallすれば問題なく処理できる。
ちゃんと引数として渡したい場合はcall :onerror "%ERRORLEVEL%"としてあげれば大丈夫だった。

:onerror内での処理の内容によっては%ERRORLEVEL%が書き換わる可能性があるため、:onerrorの先頭で変数に格納するのが安全かもしれない。

batchファイルとして私が思う完成系

最後に私の思うbatchファイルの完成系テンプレートを置いておくことにする。

@echo off
@setlocal

call :entrypoint || call :onerror
exit /b

:onerror
echo Error[%ERRORLEVEL%]
exit /b

:entrypoint
    some_commandA || exit /b !ERRORLEVEL!
    some_commandB || exit /b !ERRORLEVEL!
    some_commandC || exit /b !ERRORLEVEL!
exit /b
2
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?