【テクニカル・上級編】【構造化エラー管理】自作のエラー処理クラスによるスタックトレース擬似再現とエラー情報のコンテキスト保存 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを掌握する:構造化エラー管理による「沈黙のバグ」の根絶

VBScriptにおける `On Error Resume Next` は、諸刃の剣ではない。それは単なる「墓場」だ。安易にこれを使い、エラーを無視して処理を継続するコードは、数年後の保守担当者にとっての呪いとなる。

レガシーシステムの最前線に立つ我々にとって、エラーは「隠すもの」ではなく「記録し、解析し、再発を防ぐための資産」であるべきだ。今回は、VBScriptにおける構造化エラー管理の極致、自作エラーハンドラによるスタックトレースの擬似再現術を伝授する。

なぜ標準の Err オブジェクトでは不十分なのか

VBScriptの標準 `Err` オブジェクトは、発生した瞬間に情報を保持するが、`Err.Clear` を呼ぶか、次のエラーが発生した瞬間にその情報は霧散する。関数の呼び出し階層(コールスタック)が深くなるほど、どこで何が起きたのかという「文脈(コンテキスト)」を見失う。

我々が求めるのは、エラー発生の連鎖を保持し、再帰的にスタックを遡行できる堅牢なエラー管理オブジェクトだ。

構造化エラーハンドラ:`ErrorTracker` クラスの実装

以下のコードは、WSH環境においてエラー情報を蓄積し、ログとして出力するためのアーキテクチャである。

‘ ErrorTrackerクラス: エラーコンテキストを保持し、スタックを記録する
Class ErrorTracker
Private m_ErrorQueue

Private Sub Class_Initialize
Set m_ErrorQueue = CreateObject(“Scripting.Dictionary”)
End Sub

‘ エラーの記録(コンテキストの保存)
Public Sub Push(ByVal context, ByVal errObj)
Dim info
info = “Time: ” & Now & vbCrLf & _
“Context: ” & context & vbCrLf & _
“Number: ” & errObj.Number & vbCrLf & _
“Source: ” & errObj.Source & vbCrLf & _
“Description: ” & errObj.Description

‘ 連想配列にスタック順で格納
m_ErrorQueue.Add m_ErrorQueue.Count, info
End Sub

‘ 蓄積された全情報を文字列として取得
Public Function GetStackTrace()
Dim i, result
result = “=== Stack Trace Start ===” & vbCrLf
For i = m_ErrorQueue.Count – 1 To 0 Step -1
result = result & m_ErrorQueue(i) & vbCrLf & “—” & vbCrLf
Next
GetStackTrace = result & “=== Stack Trace End ===”
End Function

Private Sub Class_Terminate
Set m_ErrorQueue = Nothing
End Sub
End Class

実践:エラーの伝播とコンテキストの保持

関数内でエラーが発生した際、即座に終了させるのではなく、呼び出し元へエラーを伝播させつつ、情報を積み上げていく。これが高度な保守性を生む秘訣だ。

Dim tracker : Set tracker = New ErrorTracker

Sub DeepProcess()
On Error Resume Next
‘ 意図的なエラー発生(例: 存在しないオブジェクトの操作)
Dim x : x = 1 / 0
If Err.Number <> 0 Then
tracker.Push “DeepProcess: 算術演算エラー発生”, Err
Err.Raise Err.Number, Err.Source, Err.Description
End If
On Error GoTo 0
End Sub

Sub Main()
On Error Resume Next
DeepProcess
If Err.Number <> 0 Then
tracker.Push “Main: DeepProcessからのエラー捕捉”, Err
WScript.Echo tracker.GetStackTrace()
End If
On Error GoTo 0

‘ 明示的なオブジェクト解放
Set tracker = Nothing
End Sub

Main

シニアエンジニアが守るべき「極限の知見」

1. メモリ管理の鉄則

VBScriptのガベージコレクションは不完全だ。COMオブジェクトを多用する場合、`Set obj = Nothing` を怠れば、大規模なバッチ処理では確実にメモリリークを起こす。特に `Class_Terminate` 内でのオブジェクト解放を徹底せよ。

2. Windows APIの活用とリスク

WSHから `WScript.Shell` 経由でWin32 APIを叩く際は、必ず `On Error Resume Next` のスコープを最小限に絞れ。API呼び出しはOSのメモリ空間に直接干渉する。スタックトレースを記録する際、APIの戻り値(LastError)を自前で取得し、`Err.Number` と突き合わせるのがプロの作法だ。

3. レガシー環境における生存戦略

現代のWeb API連携全盛の時代にあっても、この構造化エラー管理は有効だ。JSON形式でログを吐き出せば、後段のSplunkやELKスタックへの取り込みも容易になる。VBScriptを「古い言語」と蔑むか、「システムを堅牢に支える基盤」と捉えるか。その差が、エンジニアとしての格を決める。

結びに代えて

エラーを隠すコードは、自らの首を絞める行為に等しい。エラー情報を構造化し、スタックトレースを可視化することは、システムに対する誠実さそのものである。

次に貴方が書くスクリプトには、ぜひこの「コンテキストを保存する魂」を込めてほしい。沈黙するシステムではなく、語りかけてくるシステムこそが、真に保守可能なアーキテクチャである。

タイトルとURLをコピーしました