実行時エラーに対して独自のエラー処理をするときは、On Error Resume Next ステートメントと Err オブジェクトを使う。
エラー処理の基本
On Error Resume Next ステートメントを使うと、エラー処理が有効になる。
エラー処理が有効な状態では、実行時エラーが起きても強制終了せず、そのまま処理を継続する。
エラー処理を無効にするには On Error GoTo 0 ステートメントを使う。
実行時エラーの発生有無は Err オブジェクトの Number プロパティで判定できる。
Number プロパティは、エラーがなければ 0 に、あれば 0 以外になる。
基本的なエラー処理の流れは次のとおり。
不適切なエラー処理はスクリプトの暴走につながる。注意すること。
次のサンプルは、ユーザーに入力された数値で 100 を割り、結果を表示する。
エラーが起きた場合は、エラー情報を通知して終了する。
Dim y y = InputBox("100を割る数を入力してください") '★エラー処理を有効化 On Error Resume Next Dim ret ret = 100 / y If Err.Number <> 0 Then '★エラー処理 WScript.Echo "Error # " & CStr(Err.Number) & " : " & Err.Description WScript.Quit 1 End If '★エラー処理を無効化 On Error GoTo 0 '計算結果を表示 WScript.Echo "100 ÷ " & y & " = " & ret
計算の前に入力チェックするべきだが、まぁサンプルということで。
エラー情報(Err オブジェクト)の内容
実行時エラーの内容は Err オブジェクトに格納される。
Err オブジェクトは以下のプロパティとメソッドを持つ。
Number プロパティ
エラー番号。正常なら 0 、異常なら 0 以外。
Description プロパティ
エラーの説明。
HelpFile プロパティ
ヘルプファイルのパス。
HelpContext プロパティ
ヘルプファイルのトピックを表すコンテキスト番号。
HelpFile プロパティを指定した場合、HelpContext プロパティで指定したトピックが自動的に表示される。
Source プロパティ
エラーを最初に発生させたオブジェクトの名前。
Clear メソッド
Err オブジェクトが持つすべてのプロパティの値をクリアする。
Raise メソッド
実行時エラーを生成する。
Err.Raise number [, source] [, description] [, helpFile] [, helpContext]number:
エラーの番号を Long 型の数値で指定する。
0 ~ 65535 の範囲が指定可能。
0 ~ 512 は VBScript の組み込みエラー、513 ~ はユーザー定義エラーとなる。ユーザー定義エラーは定数 vbObjectError 以上の数値にする。 たとえば、エラー番号 1050 を発生させるには vbObjectError + 1050 を指定する。
source:
エラーを生成したオブジェクトまたはアプリケーションの名前を指定する。
省略可能。description:
エラーの説明を指定する。
省略可能。helpFile:
ヘルプファイルのパスを指定する。
省略可能。helpContext:
ヘルプファイル内のトピックを識別するコンテキストIDを指定する。
省略可能。
エラー処理の適用範囲
On Error Resume Next ステートメントは使用したプロシージャにのみ適用される。
エラー処理が無効なプロシージャで実行時エラーが発生した場合、エラー処理が有効なプロシージャまで処理が渡る。
もしエラー処理が有効なプロシージャがなければ、そのままエラー情報が表示され、スクリプトは終了される。
例1)エラー処理が有効なプロシージャからエラー処理が無効なプロシージャを呼び出した場合
FuncA → FuncB で呼び出し、FuncB で実行時エラーが起きた場合、FuncA に処理が渡る。
'エラー処理が有効なプロシージャ FuncA Sub FuncA On Error Resume Next Dim ret ret = FuncB 'FuncB で実行エラーが起きた場合、ここ(FuncB を呼び出した行の次行)に処理が渡る 'エラー処理 If Err.Number <> 0 Then WScript.Echo "Error # " & CStr(Err.Number) & " : " & Err.Description WScript.Quit 1 End If End Sub 'エラー処理が無効なプロシージャ FuncB Function FuncB 'ゼロ除算エラーを起こす FuncB = 100 / 0 End Function
例2)呼び出しの階層が深くなっても考え方は同じ
FuncA → FuncB → FuncC で呼び出し、FuncC で実行時エラーが起きた場合、FuncA に処理が渡る。
'エラー処理が有効なプロシージャ FuncA Sub FuncA On Error Resume Next Dim ret ret = FuncB 'FuncB/C で実行エラーが起きた場合、ここ(FuncB を呼び出した行の次行)に処理が渡る 'エラー処理 If Err.Number <> 0 Then WScript.Echo "Error # " & CStr(Err.Number) & " : " & Err.Description WScript.Quit 1 End If End Sub 'エラー処理が無効なプロシージャ FuncB Function FuncB FuncB = FuncC End Function 'エラー処理が無効なプロシージャ FuncC Function FuncC 'ゼロ除算エラーを起こす FuncC = 100 / 0 End Function
確実にエラー処理できるようにするには
そうすることで処理されなかったすべてのエラーをキャッチできるようになる。
'メインルーチン On Error Resume Next Call Main If Err.Number = 0 Then '正常終了 WScript.Quit 0 Else '異常終了(処理されなかったすべてのエラーをここでキャッチできる) WScript.Echo "Error # " & CStr(Err.Number) & " : " & Err.Description WScript.Quit 1 End If On Error GoTo 0 'サブルーチン Sub Main 'TODO: 処理を書く End Sub
サブルーチンのエラーをメインルーチンで処理する
サブルーチンで発生したエラーを、メインルーチンで処理するようにもできる。
そうする場合、サブルーチンはエラー処理を有効化しておく。
メインルーチンは無効のままで良い。
'メインルーチン WScript.Echo Divide(100, 0) If Err.Number <> 0 Then '★サブルーチンで発生したエラーの処理 WScript.Echo "Divide Error # " & CStr(Err.Number) & " : " & Err.Description WScript.Quit 1 End If 'サブルーチン Function Divide(ByVal a, ByVal b) '★エラー処理を有効化 On Error Resume Next '実行時エラーが起きるかもしれない処理を実行 Divide = a / b End Function
VBScript ではラベルによるエラー処理はできない
以下のように On Error GoTo 〈ラベル名〉 と指定して、エラー発生時に指定したラベルへ飛ばす書き方は不可能。
'Notice: VBScript ではサポートされていない書き方 'エラーが起きたら ErrHandler ラベルに飛ばす On Error GoTo ErrHandler Dim ret ret = 100 / 0 MsgBox ret ExitHandler: Exit Sub ErrHandler: MsgBox "Error # " & CStr(Err.Number) & " : " & Err.Description GoTo ExitHandler