【極限の防衛策】AutoCADのハングアップを未然に防ぐ:バイナリレベルでのDWG/DXF破損検知の実装
業務自動化の最前線に立つエンジニアにとって、最も忌むべき事態は何か?
それは、例外処理(`On Error GoTo`)が一切通用しない、AutoCAD本体のフリーズ(ハングアップ)である。
大量の図面をバッチ処理で処理する際、たった一つの「構造的に破壊されたDWGファイル」が混入しているだけで、AutoCADのプロセスは解析ループに陥り、メモリを食いつぶし、システム全体を停止させる。この時、VBAの制御権はすでに失われており、エンジニアに残された術は「タスクマネージャーからの強制終了」という、極めて泥臭く、不格好な手段のみとなる。
本稿では、AutoCADのエンジンにファイルを渡す前段階において、Windowsの低レイヤー・バイナリアクセスを用いてファイルの「正当性」を判定する、防御的プログラミングの極致を解説する。
1. なぜ `Documents.Open` では不十分なのか
通常の開発者は、`ThisDrawing.Open` や `Documents.Open` を呼び出し、エラーが返ってくるのを待つ。しかし、これは極めて危険な設計思想である。
AutoCADのファイルオープン処理は、単なるファイル読み込みではない。ファイルヘッダーの解析、エンティティの構造検証、そしてメモリへの展開という、極めて重厚なプロセスの塊だ。ファイルヘッダーが、あるいはファイル末尾の構造が、仕様からわずかに逸脱しているだけで、AutoCADの内部パーサーは「不正なポインタ」を参照するか、あるいは「終わりのない構造探索」を開始する。
「エラーが返ってくる」ということは、AutoCADのエンジンがまだ生きていることを意味する。
我々が目指すべきは、エンジンがそのファイルに触れる前に、その「毒」を検知して排除することだ。
2. ファイルシグネチャ(Magic Number)の検証
すべてのファイル形式には、その正体を証明する「シグネチャ(マジックナンバー)」が存在する。DWGファイルは、バイナリレベルで見ると、先頭に特定のバイト列を持っている。
- DWG形式: 先頭6バイトが `AC10xx`(`xx`はバージョンを示す)というパターンを持つ。
- DXF形式: テキストベースだが、先頭に `SECTION` や特定のヘッダー構造を持つ。
これをVBAの `Open For Binary` ステートメントを用いて、メモリ負荷を最小限に抑えつつ直接読み取る。
3. 実装:バイナリ・ガード・プロトコル
以下に、AutoCADにファイルを渡す前に、そのファイルが「DWGとして最低限の構造を有しているか」を判定する、プロフェッショナル向けのモジュールを示す。
Option Explicit
' ==============================================================================
' Module: FileGuard
' Description: AutoCADのハングアップを防止するためのバイナリレベル検証モジュール
' Author: Chief Architect
' ==============================================================================
Public Enum FileValidity
Valid = 0
InvalidSignature = 1
InvalidFormat = 2
FileNotFound = 3
End Enum
''' <summary>
''' ファイルのバイナリシグネチャを検証し、AutoCADが解析不能なファイルかを判定する。
''' </summary>
''' <param name="filePath">検証対象のフルパス</param>
''' <returns>FileValidity 列挙型</returns>
Public Function VerifyFileIntegrity(ByVal filePath As String) As FileValidity
Dim fileNum As Integer
Dim signature As String
Dim buffer As String
' 1. ファイルの存在確認
If Dir(filePath) = "" Then
VerifyFileIntegrity = FileValidity.FileNotFound
Exit Function
End If
On Error GoTo ErrHandler
fileNum = FreeFile
' 2. バイナリモードでファイルを開く(共有モードを考慮)
' Lockを最小限にするため、ReadOnlyでアクセス
Open filePath For Binary Access Read As #fileNum
' 3. 先頭6バイトを読み取る (DWGのヘッダー AC10xx 用)
buffer = Space$(6)
Get #fileNum, 1, buffer
Close #fileNum
' 4. シグネチャの判定
' DWGのシグネチャは "AC10" で始まる
If Left(buffer, 4) = "AC10" Then
VerifyFileIntegrity = FileValidity.Valid
Else
' DXFの簡易判定 (テキストベースのため、先頭に特定の文字列があるか)
' 本来はより厳密なチェックが必要だが、ここでは概念を示す
If InStr(1, buffer, "SECTION", vbTextCompare) > 0 Then
VerifyFileIntegrity = FileValidity.Valid
Else
VerifyFileIntegrity = FileValidity.InvalidSignature
End If
End If
Exit Function
ErrHandler:
If fileNum > 0 Then Close #fileNum
VerifyFileIntegrity = FileValidity.InvalidFormat
End Function
''' <summary>
''' 安全なファイルオープン・ルーチン
''' </summary>
Public Sub SafeOpenDocument(ByVal filePath As String)
Dim status As FileValidity
Dim doc As AcadDocument
' --- Pre-flight Check (事前飛行点検) ---
status = VerifyFileIntegrity(filePath)
Select Case status
Case FileValidity.Valid
Debug.Print "Integrity Verified: " & filePath
' ここで初めてAutoCADエンジンに制御を渡す
On Error Resume Next
Set doc = ThisDrawing.Application.Documents.Open(filePath)
If Err.Number <> 0 Then
MsgBox "AutoCAD内部エラー: " & Err.Description, vbCritical
End If
On Error GoTo 0
Case FileValidity.InvalidSignature
' 破損の可能性が高い。AutoCADに渡さず、ログに記録してスキップする
LogError filePath, "Invalid Binary Signature (Possible Corruption)"
MsgBox "致命的なエラー: ファイル構造が不正です。解析を中止します。", vbCritical
Case FileValidity.InvalidFormat
LogError filePath, "Format Error during Binary Read"
MsgBox "ファイル読み取りエラーが発生しました。", vbExclamation
Case FileValidity.FileNotFound
MsgBox "ファイルが見つかりません。", vbExclamation
End Select
' オブジェクトの明示的な解放(メモリ管理の鉄則)
Set doc = Nothing
End Sub
Private Sub LogError(ByVal path As String, ByVal msg As String)
' 実際の実装では、DBやテキストログに詳細を書き出す
Debug.Print "[CRITICAL ERROR] " & path & " | " & msg
End Sub
4. アーキテクトの視点:メモリ管理と堅牢性の設計
このコードを実装する際、単に「動く」ことだけを求めてはいけない。以下の3点に、プロフェッショナルの魂を込める。
I. オブジェクトのライフサイクル管理
`Set doc = Nothing` を忘れてはならない。特にバッチ処理のように数千個のファイルをループで回す場合、参照カウントが適切に解放されないと、VBAのメモリ空間が肥大化し、最終的に `Out of Memory` を引き起こす。これはファイル破損とは別の、自壊的なエラーである。
II. ファイルロックの競合回避
`Open … For Binary Access Read` を使用しているのは、ファイルが他のプロセス(あるいはAutoCAD自身)によって書き込みロックされていても、読み取り専用としてアクセスを試みるためだ。`Access Read` を指定しない場合、ロックされているファイルに対してエラーを吐き、処理が中断してしまう。
III. エラーハンドリングの階層化
エラーハンドリングは「二段構え」で行う。
1. 第一層(バイナリ層): `VerifyFileIntegrity` による、エンジンの外側での判定。
2. 第二層(API層): `Documents.Open` による、エンジン内部での判定。
この二重の防壁こそが、システム全体の稼働率(Uptime)を決定づける。
結論
シニアエンジニアに求められるのは、APIの便利な使い方を知っていることではない。「APIが壊れる条件」を知っていることだ。
AutoCADという巨大なブラックボックスを制御するならば、その境界線(インターフェース)を物理的なバイナリレベルでガードせよ。それが、レガシーな環境においても、最新のアーキテクチャにおいても、揺るぎない信頼性を生む唯一の道である。
