プロフェッショナルのためのVB.NET:アプリケーションを「落とさない」最終防衛ラインの構築術
現場で「なぜか落ちる」という報告を受けるたび、私はそのコードの脆さを痛感する。業務自動化ツールにおいて、予期せぬ例外は避けて通れない。だが、「例外が発生したからアプリが落ちました」は、エンジニアとして最も言ってはならない言い訳だ。
真のプロフェッショナルは、アプリケーションの「死に際」を制御する。今日は、VB.NETアプリケーションをクラッシュから守り、事後検証を可能にする「最終防衛ライン」の設計について、核心を突く実装法を伝授する。
—
1. なぜ「Try-Catch」だけでは不十分なのか
多くの初学者は、各メソッド内で `Try…Catch` を羅列する。しかし、それは「局部的な鎮痛剤」に過ぎない。
- 非同期処理: 新しいスレッドで発生した例外は、親スレッドのTry-Catchをすり抜ける。
- イベントハンドラ: GUI操作に伴う未処理例外は、即座にアプリケーションの強制終了(プロセス消滅)を引き起こす。
- メモリリーク・リソース解放: クラッシュ時には `Finally` ブロックが実行されないケースがあり、ファイルロックやDB接続が中途半端に残るリスクがある。
これらを一括で受け止め、安全にシャットダウンさせるための「最後の砦」が `AppDomain.UnhandledException` イベントだ。
—
2. 最終防衛ラインの実装:プロダクションコード
以下のコードは、アプリケーションの起動時(`Sub Main` または `Application_Startup`)に一度だけ呼び出すべき「番人」である。これを実装することで、アプリが死ぬ瞬間のスタックトレースを確実にログへ焼き付けることが可能になる。
Imports System
Imports System.IO
Imports System.Windows.Forms
Public Class ErrorManager
”’
”’
Public Shared Sub InitializeGlobalExceptionHandler()
‘ AppDomainレベルの未処理例外をキャッチ
AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf CurrentDomain_UnhandledException
End Sub
Private Shared Sub CurrentDomain_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs)
Dim ex As Exception = TryCast(e.ExceptionObject, Exception)
‘ 1. 緊急ログの保存(ファイルシステムが死んでいないことを前提とした最速の書き込み)
Dim logPath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, “emergency_crash.log”)
Try
Dim logContent As String = $”[{DateTime.Now}] CRITICAL ERROR: {ex?.Message}{Environment.NewLine}{ex?.StackTrace}”
File.AppendAllText(logPath, logContent)
Catch
‘ ファイルアクセスエラーが発生した場合、イベントログに逃がす等のフォールバックが必要
End Try
‘ 2. ユーザーへの通知(UIスレッドの状態を考慮)
MessageBox.Show(“致命的なエラーが発生しました。作業内容を保存できているか確認し、管理者に連絡してください。” & vbCrLf &
“エラーログ: ” & logPath, “システムエラー”, MessageBoxButtons.OK, MessageBoxIcon.Error)
‘ 3. アプリの終了(プロセスを不正終了させず、リソースを解放して終了)
Environment.Exit(1)
End Sub
End Class
—
3. 実務で「落ちない」ための設計指針
この防衛ラインを設置したからといって、例外を放置していいわけではない。堅牢なツールの要件は以下の3点だ。
① 「状態」の永続化を疎結合にする
ファイルやDBへの書き込み中にクラッシュすると、データが破損する。
- 対策: データの保存は「一時ファイルに書き出し → 本物とリネーム(アトミック操作)」という手順を踏むこと。リネームはOSレベルで完了するため、途中で落ちてもデータが壊れる確率は格段に下がる。
② リソースの所有権を明確にする
`Using` ステートメントを使わないVB.NETコードは、業務自動化の世界では「爆弾」だ。
- 対策: IDisposableインターフェースを持つオブジェクト(Stream, Connection, Command)は、例外発生時であっても確実に解放されるよう、必ず `Using` 構文の中で生成する。
③ ユーザーに「状況」を伝える
ただ落ちるだけでは、ユーザーは不安になる。
- 対策: 「何が起きたか」「次に何をすべきか」をログに含める。特に、ネットワークドライブの切断やDBのタイムアウトなど、外部要因によるエラーはログに「切り分け」ができる情報を吐き出させること。
—
最後に:エンジニアとしての矜持
コードを書くことは、魔法を作ることではない。「失敗したとき、どう振る舞うか」というシナリオを記述することこそが、本当のエンジニアリングだ。
今日紹介した `UnhandledException` は、あなたのツールに「プロの顔」を与える。突然の死を恐れるな。死に際を美しく制御できる者だけが、真に信頼される自動化ツールを生み出すことができる。
君たちの書くコードが、明日の業務をより快適にすることを期待している。健闘を祈る。
