【上級プロフェッショナル向け】バイナリレベルでの「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の基本、そして「実戦的な設計思想」はバッチリですよ。さあ、次のステップへ進みましょう!
