AutoCAD VBAを掌握する極限の知見
【上級】AcadApplication.ListArxとLoadArxによる「ObjectARXアドイン」の動的ロードと依存関係管理
多くのVBAプログラマは、AutoCADの標準オブジェクト操作、すなわち `AcadDocument` や `AcadModelSpace` の制御で満足する。しかし、真のインフラストラクチャを構築するシニアエンジニアにとって、VBAは単なるマクロ言語ではなく、C++ベースのObjectARXエコシステムとAutoCADのコアプロセスを橋渡しする「極めて強力なオーケストレーション・レイヤー」に変貌する。
本稿では、エンタープライズ環境におけるCAD自動化のボトルネックを打破するため、`AcadApplication.ListArx` と `AcadApplication.LoadArx` を駆使したObjectARXアドインの動的ロードおよび依存関係管理ランチャーの実装手法を解き明かす。
—
1. なぜVBAからARXを動的制御する必要があるのか?
大規模な設計現場やプラントエンジニアリングの現場では、カスタムエンティティ(独自オブジェクト)や高度な幾何学演算を提供する自社製・サードパーティ製のObjectARX(`.arx`)アドインが不可欠だ。
しかし、ここで重大なアーキテクチャ上の課題が生じる。
- 起動時間の肥大化: AutoCAD起動時にすべてのARXを自動ロード(`acad.rx`等による静的ロード)させると、メモリ消費が増大し、プレーンな図面を開くだけでもパフォーマンスが低下する。
- 競合と依存関係の欠落: 特定のVBAスクリプトが依存するARXがロードされていない場合、メソッドの呼び出しに失敗し、容赦なく致命的なランタイムエラー(エラー 438: オブジェクトは、このプロパティまたはメソッドをサポートしていません)が発生する。
この課題を解決するのが、「必要時に、必要な分だけ、安全にARXをロードする」 動的依存関係管理システムである。
—
2. コア・オブジェクトモデルと知られざる仕様
AutoCADのアプリケーションルートである `AcadApplication` オブジェクトには、ARXモジュールを直接操作するためのネイティブなメソッドとプロパティが用意されている。
1. `ListArx()` 方法:
現在メモリ上にロードされているすべてのObjectARXモジュールのリストを、文字列配列(Variant)として返す。
2. `LoadArx(ModuleName As String)`:
指定したパス、またはサポートパス上のARXモジュールを動的にロードする。
3. `UnloadArx(ModuleName As String)`:
メモリから指定モジュールをアンロードする(※メモリリークや未解放ポインタの温床となるため、実務では極めて慎重なハンドリングが要求される)。
ここでエンジニアが直面する最初の壁は、`ListArx` が返す配列の扱いである。AutoCADのCOMインターフェース仕様において、配列の境界(Lower/Upper Bound)やVariant型のバリアント処理は、C++のメモリモデルの挙動を引きずっているため、安易なイテレーションは予期せぬType Mismatchを引き起こす。
—
3. 実装:堅牢なARX動的ランチャー&依存関係マネージャー
以下のコードは、実務の現場でそのまま稼働する、堅牢なエラーハンドリングとメモリ最適化を組み込んだクラスモジュールの実装例である。
Option Explicit
”================================================================
” Class Module: clsArxManager
” Description: ObjectARXモジュールのロード状態監視と動的依存関係管理
”================================================================
Private m_App As AcadApplication
Private Sub Class_Initialize()
‘ アプリケーションインスタンスの遅延バインディングおよび参照保持
‘ 新規インスタンス生成ではなく、実行中のAcadAppを正確にキャプチャする
Set m_App = ThisDrawing.Application
End Sub
Private Sub Class_Terminate()
‘ 循環参照の防止と明示的なオブジェクト解放
Set m_App = Nothing
End Sub
Public Function IsArxLoaded(ByVal arxName As String) As Boolean
Dim arxList As Variant
Dim i As Long
Dim targetName As String
IsArxLoaded = False
targetName = UCase(Trim(arxName))
On Error GoTo ErrorHandler
‘ 現在ロードされているARXのリストを取得
arxList = m_App.ListArx()
‘ 配列が空(何もロードされていない)の場合のガード
If Not IsArray(arxList) Then Exit Function
For i = LBound(arxList) To UBound(arxList)
‘ 大文字小文字を区別せずに一致確認(拡張子有無の両方に対応)
If UCase(Trim(arxList(i))) = targetName Or _
UCase(Trim(arxList(i))) = targetName & “.ARX” Then
IsArxLoaded = True
Exit For
End If
Next i
ErrorHandler:
If Err.Number <> 0 Then
‘ ログ出力機構へのルーティング(ここではイミディエイト出力)
Debug.Print “[ArxManager Error] IsArxLoaded: ” & Err.Description
End If
End Function
Public Function EnsureArxLoaded(ByVal fullPath As String, ByVal moduleName As String) As Boolean
EnsureArxLoaded = False
On Error GoTo LoadError
‘ 既にロードされているかチェック
If IsArxLoaded(moduleName) Then
EnsureArxLoaded = True
Exit Function
End If
‘ ファイルの存在確認(FileSystemObjectの利用を推奨するが簡略化)
If Dir(fullPath) = “” Then
Err.Raise vbObjectError + 1000, “ArxManager”, “指定されたARXファイルが存在しません: ” & fullPath
End If
‘ 動的ロードの実行
m_App.LoadArx fullPath
‘ ロード確認の再検証
If IsArxLoaded(moduleName) Then
EnsureArxLoaded = True
Debug.Print “[ArxManager] Successfully loaded: ” & moduleName
Else
Err.Raise vbObjectError + 1001, “ArxManager”, “ARXのロード命令は実行されましたが、メモリ上に確認できませんでした: ” & moduleName
End If
Exit Function
LoadError:
MsgBox “ObjectARXアドインのロードに失敗しました。” & vbCrLf & _
“モジュール: ” & moduleName & vbCrLf & _
“詳細: ” & Err.Description, vbCritical, “致命的なシステムエラー”
EnsureArxLoaded = False
End Function
—
4. 現場で生きる:呼び出し側の実装パターン
上記のマネージャーを使用することで、VBAのメイン処理は非常にクリーンになり、依存関係の保証が確実に行われる。
Sub ExecuteCustomCommandWithArx()
Dim arxMgr As clsArxManager
Set arxMgr = New clsArxManager
Dim arxPath As String
Dim arxName As String
‘ 社内標準の独自ジオメトリ演算ARXのパスを指定
arxName = “StructuralCoreEngine”
arxPath = “C:\EnterpriseCAD\Plugins\StructuralCoreEngine.arx”
‘ 1. 依存関係の解決(未ロードならこの瞬間にロードされる)
If Not arxMgr.EnsureArxLoaded(arxPath, arxName) Then
‘ ロード失敗時は処理をアボート
Set arxMgr = Nothing
Exit Sub
End If
‘ 2. ARXが提供するネイティブコマンドをSendCommandで実行、
‘ またはレイターバインドされたCOMインターフェースを操作
ThisDrawing.SendCommand “_MyCustomStructuralCommand ”
‘ クリーンアップ
Set arxMgr = Nothing
End Sub
—
5. チーフアーキテクトからの警鐘:メモリ管理とライフサイクルの罠
この高度な手法を採用するにあたり、シニアエンジニアとして知っておくべき「暗黙の罠」が存在する。
- メモリリークとアンロードの危険性:
`UnloadArx` をVBA側から無秩序に呼び出すことは推奨しない。ObjectARX内部で確保されたカスタムエンティティのメモリやアロケーションが不完全に破棄された場合、AutoCADプロセス全体の不安定化(クラッシュ)を招く。原則として、ARXのアンロードはAutoCADのセッション終了時に任せるか、厳密な参照カウント管理が実装されたC++側で制御させるべきである。
- セキュリティコンテキスト(デジタル署名):
近年のAutoCAD(AutoCAD 2023以降など)では、信頼されていないパスからのARXロードはセキュリティポリシーによってブロックされる場合がある。`LoadArx` を実行する前に、対象のパスが信頼できる場所(TRUSTEDPATHS)に登録されているか、あるいはデジタル署名が有効であるかをインフラ側で担保しておく必要がある。
総括
VBA単体の限界にとらわれず、`AcadApplication.ListArx` と `LoadArx` を通じてC++アドインの世界を自在にコントロールすること。これこそが、レガシーとモダンを繋ぐプロフェッショナル・エンジニアリングの真髄である。自社の自動化基盤にこの動的依存関係管理を組み込み、メンテナンスフリーで強靭なCADエコシステムを構築してほしい。
