怠日記

写真・金魚・昆虫・プログラミングの趣味を語るサイトです。似たようなことをnoteにも書いたり書いてなかったり。

VBScript - エラー処理

スクリプトの実行中にエラーが起きた場合、通常、その時点でスクリプトは強制終了される。

実行時エラーに対して独自のエラー処理をするときは、On Error Resume Next ステートメントErr オブジェクトを使う。

エラー処理の基本

On Error Resume Next ステートメントを使うと、エラー処理が有効になる。

エラー処理が有効な状態では、実行時エラーが起きても強制終了せず、そのまま処理を継続する。

エラー処理を無効にするには On Error GoTo 0 ステートメントを使う。


実行時エラーの発生有無は Err オブジェクトの Number プロパティで判定できる。

Number プロパティは、エラーがなければ 0 に、あれば 0 以外になる。


基本的なエラー処理の流れは次のとおり。

  1. エラーの発生が想定される処理の前に On Error Resume Next ステートメントを置いて、エラー処理を有効化
  2. 処理を実行
  3. Err.Number <> 0 だったらエラー処理する
  4. On Error GoTo 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 ステートメントを使う。

そうすることで処理されなかったすべてのエラーをキャッチできるようになる。

'メインルーチン
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 ではラベルによるエラー処理はできない

VBScript では VB6 や VBA にあるラベルによるエラー処理は利用できない。

以下のように 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