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

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

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

「AutoCADが……固まった。」

業務自動化のプロフェッショナルとして、あるいは意欲的なマクロ開発者として、これほど絶望的な瞬間はありません。大量の図面をバッチ処理している最中、ある一つの「壊れたファイル」に出会った瞬間、AutoCAD本体が応答なし(ハングアップ)になり、全ての処理が水の泡になる。

これは、AutoCAD VBAの初心者なら誰もが通る道であり、ベテランでも時折頭を抱える「実戦における最大の壁」の一つです。

なぜ、`Documents.Open` メソッドは、壊れたファイルに対してこれほどまでに無力なのか? そして、私たちはどうすれば、AutoCADという巨大なエンジンが「不正なデータ」を飲み込んで沈没する前に、それを食い止めることができるのか?

今日は、APIの表面的な使い方を超え、ファイルの「正体」をバイナリレベルで暴く、プロフェッショナルのための防御策を伝授します。

1. なぜ `Documents.Open` はフリーズするのか?

まず、問題の本質を理解しましょう。

通常のプログラミングでは、エラーが起きれば「エラー処理(Error Handling)」によって制御を戻せます。しかし、AutoCADのような巨大なアプリケーションにおいて、ファイル構造そのものが致命的に壊れている場合、AutoCADの内部解析エンジン(Parser)が、不正なメモリ領域にアクセスしようとしたり、無限ループに陥ったりすることがあります。

この時、VBA側で `On Error Resume Next` と書いても、AutoCADという「器(プロセス)」そのものがフリーズしているため、VBAの制御権が戻ってこないのです。

これを防ぐ唯一の方法は、「AutoCADにファイルを渡す前に、人間(プログラム)がそのファイルの中身を検閲する」ことです。

2. 「マジックナンバー」という名の身分証明書

全てのファイル形式には、そのファイルが何であるかを証明する「マジックナンバー(シグネチャ)」と呼ばれる数バイトのデータが、ファイルの先頭に書き込まれています。

  • DWGファイルの場合: 先頭に `AC10` に続くバージョンコード(例:`AC1032`)が書き込まれています。
  • DXFファイルの場合: テキスト形式なので、先頭付近に `SECTION` などの特定の文字列が存在します。

もし、ファイル拡張子が `.dwg` なのに、先頭のバイナリが `AC` で始まっていなければ、それは偽物、あるいは破損したファイルです。これを「開く前」に判定できれば、AutoCADがフリーズするのを未然に防げます。

3. 実装:バイナリ・プレチェック・エンジン

それでは、実際に使えるコードを見てみましょう。ここでは、ファイルの先頭数バイトを「バイナリモード」で読み取り、DWGまたはDXFとして正当なヘッダーを持っているかを判定する関数を作成します。

Option Explicit

''' <summary>
''' ファイルのヘッダーをバイナリレベルで検証し、
''' AutoCADが読み込める可能性が高いファイルかどうかを判定する。
''' </summary>
''' <param name="filePath">検証するファイルのフルパス</param>
''' <returns>正当な形式ならTrue、不正または破損ならFalse</returns>
Public Function IsValidDrawingFile(ByVal filePath As String) As Boolean
    On Error GoTo ErrHandler
    
    Dim fileNum As Integer
    Dim headerBytes(0 To 5) As Byte ' 先頭6バイトを格納するバッファ
    Dim fileExt As String
    Dim headerStr As String
    
    ' 1. ファイルの存在確認
    If Dir(filePath) = "" Then
        IsValidDrawingFile = False
        Exit Function
    End If
    
    ' 2. 拡張子の取得
    fileExt = LCase(Mid(filePath, InStrRev(filePath, ".") + 1))
    
    ' 3. バイナリモードでファイルを開く
    ' ここがポイント:Open ... For Binary を使うことで、テキスト変換を介さず生データを読み取る
    fileNum = FreeFile
    Open filePath For Binary Access Read As #fileNum
    
    ' 先頭6バイトを読み込む
    Get #fileNum, 1, headerBytes
    Close #fileNum
    
    ' 4. バイト配列を文字列(または判定用データ)に変換
    ' DWGのシグネチャは "AC" (Hex: 41 43) から始まる
    ' 例: AC1015, AC1024, AC1032 など
    
    If fileExt = "dwg" Then
        ' DWGのチェック: 先頭2バイトが 'A' (41) と 'C' (43) か?
        If headerBytes(0) = &H41 And headerBytes(1) = &H43 Then
            IsValidDrawingFile = True
        Else
            IsValidDrawingFile = False
        End If
        
    ElseStep:
    If fileExt = "dxf" Then
        ' DXFのチェック: テキストとして "SECTION" 等が含まれるか(簡易判定)
        ' バイナリを文字列に変換してチェック
        headerStr = StrConv(headerBytes, vbUnicode)
        ' DXFはテキストなので、先頭付近に特定のパターンがあるかを確認
        ' ここでは簡易的に、読み込んだデータが空でないことを確認
        If Len(headerStr) > 0 Then
            IsValidDrawingFile = True
        Else
            IsValidDrawingFile = False
        End If
    Else
        ' 対応外の拡張子
        IsValidDrawingFile = False
    End If
    
    Exit Function

ErrHandler:
    ' ファイルが開けない、読み取れない等のエラーが発生した場合
    If fileNum > 0 Then Close #fileNum
    IsValidDrawingFile = False
End Function

''' <summary>
''' メイン実行ルーチン:安全なファイルオープン・プロセス
''' </summary>
Public Sub SafeOpenProcess()
    Dim targetFile As String
    targetFile = "C:\Temp\Test_Corrupted.dwg" ' テスト用のパス
    
    Debug.Print "--- 検証開始: " & targetFile & " ---"
    
    ' 【極限の知見】AutoCADのAPIを叩く前に、必ずこのチェックを通す!
    If IsValidDrawingFile(targetFile) Then
        Debug.Print "結果: [PASS] 正当なファイルです。AutoCADで開きます。"
        ' ここで初めて AutoCAD の Documents.Open を実行する
        ' ThisDrawing.Documents.Open targetFile
    Else
        Debug.Print "結果: [FAIL] 破損または不正なファイルです。オープンを中止しました。"
        MsgBox "警告: ファイルが破損しているか、DWG形式ではありません。" & vbCrLf & _
               "AutoCADのフリーズを回避するため、処理をスキップしました。", vbCritical
    End If
End Sub

4. コードの解説と、陥りやすい罠

なぜ `Binary Access Read` なのか?

通常の `Open … For Input` を使うと、VBAはファイルを「テキストファイル」として解釈しようとします。しかし、DWGはバイナリファイルです。テキストとして読み込むと、改行コードや特殊文字の解釈によってデータが書き換わってしまい、正確なシグネチャ判定ができなくなります。`Binary` モードを使うことで、「ファイルの中身をそのまま、1ビットも変えずに覗き見る」ことが可能になります。

陥りやすいエラー:ファイルロック

もし、そのファイルが既に他のプロセス(あるいは既に開いているAutoCAD)によって完全にロックされている場合、`Open` 文自体がエラーを吐きます。`ErrHandler` を用意し、エラー時には必ず `Close #fileNum` を実行して、ファイルハンドルを解放することを忘れないでください。これを忘れると、次にそのファイルを開こうとした時に「別のプロセスが使用中です」という新たな問題を引き起こします。

判定の精度について

上記のコードは、あくまで「致命的な破損(ファイルが全く別物であること)」を検知するためのものです。DWGの内部構造が細かく壊れている(例:レイヤー定義が欠落している等)場合は、このチェックを通り抜けます。しかし、「AutoCADが即座にハングアップするような、ヘッダーレベルの破壊」は、これで確実に防げます。

5. まとめ:エンジニアとしての「品格」

プログラミングにおける「上級者」とは、単に複雑なアルゴリズムを書ける人のことではありません。「システムがどのように壊れるか」を予見し、その壊れ方に対して事前にバリアを張れる人のことです。

`Documents.Open` という強力な武器を、むやみに振り回してはいけません。
1. まず、ファイルが実在するか確認する (`Dir`)
2. 次に、バイナリレベルで身分を証明させる (`Open For Binary`)
3. 最後に、安全が確認できてから、AutoCADに委ねる (`Documents.Open`)

この3ステップを守るだけで、あなたの作る自動化ツールは、現場のエンジニアから「絶対に止まらない、信頼できるツール」として絶大な信頼を得ることになるでしょう。

ここをクリアすれば、AutoCAD VBAの基本、そして「実戦的な設計思想」はバッチリですよ。さあ、次のステップへ進みましょう!

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