【テクニカル・上級編】【上級プロフェッショナル向け】バイナリレベルでの「DWG/DXF破損」判定:AutoCAD APIがフリーズする前に不正ファイルを検知する – AutoCAD VBA解析バイブル

スポンサーリンク
スポンサーリンク

【極限の防衛策】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という巨大なブラックボックスを制御するならば、その境界線(インターフェース)を物理的なバイナリレベルでガードせよ。それが、レガシーな環境においても、最新のアーキテクチャにおいても、揺るぎない信頼性を生む唯一の道である。

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