VB6 実行時エラーのコールスタックを採取する小ネタ
VB6 で、エラーをハンドリングする際のスケルトン。例によって VB6 に限定しているのは、.NET はまだ仕事で使ってないので語るものを持たないためです。
エラーを必ずハンドリングする必要があるのは、呼出元を持たないプロシージャ、つまり、Sub Main() 、イベントプロシージャ、またはコールバックプロシージャ(ウインドウをサブクラス化した時のウインドウプロシージャとか、フックプロシージャのこと)などで、自分自身が大元の呼び出し元であるプロシージャ達です。それ以外のエラーは呼出元に返すことができます。
呼出元に返す際に、 Err オブジェクトにプロシージャ名をセットしていくと、前述の呼出元プロシージャでは、呼出順をとることができます。
'イベントプロシージャ Option Explicit Private Const MODULE_NAME As String = "Form1" '------------------------------------------------------------------ 'プロシージャ名: :Form_Initialize '説明: : '------------------------------------------------------------------ Private Sub Form_Initialize() '============= Declare ============== '============= Initiarize =========== On Error GoTo ErrorHandler '============= Main ================= ' 処理... '============= Release ============== ExitHandler: Exit Sub '============= Error ================ ErrorHandler: Call HandleError(Err.Number, Err.Source, Err.Description, MODULE_NAME & ".Form_Initialize") Resume ExitHandler End Sub
HandleError って関数の中で、ログをはくなりしましょうってイメージ。
で、その他のプロシージャ。要するに間接的に呼び出されるやつ。ここでは、Err.Source にコールスタックを格納していきます。
'その他プロシージャ Option Explicit Private Const MODULE_NAME As String = "Module1" '****************************************************************** 'プロシージャ名: :MyGeneralProcedure '説明: :エラー処理に注目 '****************************************************************** Public Sub MyGeneralProcedure() '============= Declare ============== '============= Initiarize =========== On Error GoTo ErrorHandler '============= Main ================= ' 処理... '============= Release ============== ExitHandler: Exit Sub '============= Error ================ ErrorHandler: Call Err.Raise(Err.Number, MODULE_NAME & ".MyGeneralProcedure ← " & Err.Source, Err.Description, Err.HelpFile, Err.HelpContext) End Sub
こんな感じで、たとえば Class1 というクラスモジュールに MyProperty というプロパティがあり、そのなかで、Module1 という標準モジュールの MyGeneralProcedure をコールしていて、そこで実行時エラーが起こった場合、呼出元に返った時の、Err.Source は、
Class1.MyProperty ← Module1.MyGeneralProcedure ← OriginalErrorSource
のようになります。障害時の追跡に決行役に立つものです。
トラックバック
- このエントリーにトラックバック:
- http://frog.raindrop.jp/cgi-bin/mt/mt-tb.cgi/791
コメント
クラスは、MODULE_NAMEとしなくてもTypeName(Me)で
クラス名が取れますよ。標準モジュールはだめです。
>ふぅさん
コメントありがとうございます。
そうですね、フォーム、またはクラスモジュールのみで構築できれば
最も可搬性の高い方法ですね。
残念ながら、VC++ で作成した DLL よりコールバックするようなつくりの多い私の場合は、
標準モジュールを駆逐することはできないです・・・
美しくない・・・