AutoCAD自動化の壁を砕く:プロキシ警告を無力化し、DWG処理を完全自動化する極意
AutoCADの自動化において、最も忌むべきは「処理の停止」だ。
アドオンソフトで作成された未知のオブジェクト、あるいは他社から送られてくる素性の知れない図面。これらを開く際に画面を覆う「プロキシ情報」のダイアログは、我々エンジニアにとっての死神だ。
バッチ処理を仕掛けた翌朝、出社してみれば画面がダイアログで埋め尽くされ、処理が開始から数秒で停止している……そんな惨状を経験したことはないだろうか。
今回は、この「見えない壁」をシステム変数で完封し、さらにメモリアロケーションの観点から安定性を極限まで高める方法を伝授する。
—
1. プロキシ抑制の正攻法:システム変数の「真の制御」
プロキシダイアログを止めるには `PROXYNOTICE` を制御するのが定石だが、実はこれだけでは不十分だ。環境によっては `PROXYGRAPHICS` や `FILEDIA` が絡み合い、意図せぬ挙動を引き起こす。
真のアーキテクトは、単に値を書き換えるのではなく、「処理開始前の状態を記憶し、終了後に確実に復帰させる」というプロトコルを遵守する。
実装コード:堅牢なオープン処理の定石
‘ AutoCAD VBA: プロキシ警告を無力化して図面をサイレントオープンする
Public Sub OpenDrawingSecurely(ByVal filePath As String)
Dim acadApp As Object
Dim acadDoc As Object
‘ 既存のシステム変数を退避(スタック構造のシミュレーション)
Dim originalProxyNotice As Integer
Dim originalFileDia As Integer
Set acadApp = Application
‘ プロキシ警告を抑制 (0: 非表示)
originalProxyNotice = acadApp.GetVariable(“PROXYNOTICE”)
acadApp.SetVariable “PROXYNOTICE”, 0
‘ ファイルダイアログを抑制 (0: コマンドライン実行)
originalFileDia = acadApp.GetVariable(“FILEDIA”)
acadApp.SetVariable “FILEDIA”, 0
On Error GoTo ErrorHandler
‘ 図面を開く
Set acadDoc = acadApp.Documents.Open(filePath)
‘ 【重要】処理が終わったら即座にリセット
‘ ここで例外が発生しても復帰できるよう、処理の整合性を担保する
Cleanup:
acadApp.SetVariable “PROXYNOTICE”, originalProxyNotice
acadApp.SetVariable “FILEDIA”, originalFileDia
Exit Sub
ErrorHandler:
MsgBox “図面オープン中に致命的なエラーが発生しました: ” & Err.Description
Resume Cleanup
End Sub
—
2. メモリ最適化:VBAが抱える「ゾンビオブジェクト」を消し去れ
VBAはガベージコレクションが脆弱だ。AutoCADのCOMオブジェクトは、明示的に `Nothing` を代入しても、内部のポインタが解放されないケースが多々ある。特にループ内で `Documents.Open` を繰り返す処理では、メモリリークが蓄積し、数千枚の図面処理で必ずAutoCADはクラッシュする。
極限の知見:オブジェクトのライフサイクル管理
`Set acadDoc = Nothing` だけで満足してはいけない。以下の手法を取り入れることで、メモリ消費の安定化を図る。
- 明示的なメモリフラッシュ: `DoEvents` を適切に挟み、Windows OSへのコンテキストスイッチを促す。
- クリーンアップの徹底: 処理終了後は `acadDoc.Close False` を行い、ドキュメントのライフサイクルを強制終了させる。
—
3. レガシー環境への配慮:Windows APIの介入
もし、どうしてもシステム変数が効かない特殊な環境(古いAutoCADやカスタマイズされた垂直アプリケーション)に遭遇した場合は、Windows APIを使用してダイアログのウィンドウハンドル(HWND)を直接探し出し、プログラム的に「閉じる」という荒技が必要になる。
これを行うには `FindWindow` や `SendMessage` を駆使するが、これは最終手段だ。
‘ APIを使用したウィンドウ強制クローズの概念
Private Declare PtrSafe Function FindWindow Lib “user32” Alias “FindWindowA” _
(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
‘ ※注意:AutoCADのダイアログクラス名はバージョンにより変動するため、
‘ Spy++等で調査した上で実装すること。
—
チーフアーキテクトの提言
自動化の現場において「例外」は必ず発生する。我々が書くコードは、正常系を動かすためのものではなく、「異常系をいかに無音で通過させるか」のために存在する。
1. システム変数は必ずバックアップを取れ。
2. ループ処理では必ず `DoEvents` を使い、OSの息継ぎをさせろ。
3. ダイアログは表示される前に「存在」を封じ込めろ。
この3点を守るだけで、君のAutoCAD自動化システムは、夜通し止まることのない強固なエンジンへと進化するはずだ。技術は裏切らない。コードの隅々にまで、君の意志を刻み込め。
