【上級】AcadApplication.Preferences.Filesを操作し、社内標準のサポートパスを自動追加・同期
CAD管理者にとって、PCの入れ替えや拠点間での設計環境の差異ほど頭を悩ませるものはない。フォントの置き換わり、カスタム線種の欠落、ブロックのリンク切れ――これらはすべて「サポートファイルの検索パス」の不整合に起因する。
手動での設定はヒューマンエラーの温床であり、数百台のクライアント端末に対してそれを強いるのはインフラ管理の怠慢に等しい。
今回は、`AcadApplication.Preferences.Files` を極限まで利用し、起動時に社内標準のサポートパスを動的に検証・再構築・同期する、プロダクション品質のVBAアーキテクチャを提示する。
—
1. 根幹をなすアーキテクチャの設計思想
AutoCADの環境設定(`Preferences` オブジェクト)は、Windowsレジストリおよび内部のプロファイルに深く結びついている。これをVBAから安全に操作するためには、以下の3点を死守しなければならない。
1. 文字列のパースと重複排除: サポートパスはセミコロン(`;`)区切りの巨大な文字列である。単純な追加を繰り返すと、同一パスが重複してパフォーマンスが低下し、文字列長制限(一般的に2048文字)に抵触する。
2. ネットワークパスのフォールバックと存在確認: 存在しないネットワークパス(NAS等)を無理やり追加すると、ファイル検索時にAutoCADがフリーズ(タイムアウト待ち)を起こす。VBAからFileSystemObject(FSO)を用いて物理存在を確認してから追加する。
3. トランザクション的思考: 設定の変更途中でエラーが発生した場合を考慮し、退避(バックアップ)とロールバックの概念をコードに組み込む。
—
2. 実装コード:社内標準パス自動同期エンジン
以下のコードは、単にパスを追加するだけの稚拙なものではない。既存のパス構造を解析し、社内標準(マスター)が確実に優先順位の最上位、あるいは指定の位置に存在するように同期するプロフェッショナル向けの実装である。
Option Explicit
‘================================================================================モジュール名: clsPathSynchronizer
‘ 概要: AutoCADのサポートファイル検索パスを社内標準に同期するクラス
‘================================================================================
Private Const STANDARD_PATHS As String = “\\server\cad_standard\fonts;\\server\cad_standard\lin;\\server\cad_standard\block”
Private Const DELIMITER As String = “;”
Public Sub SynchronizeSupportPaths()
Dim acadPref As AcadPreferencesFiles
Dim rawPaths As String
Dim pathArray() As String
Dim standardArray() As String
Dim optimizedPaths As String
Dim fso As Object
Dim i As Long, j As Long
Dim isModified As Boolean
On Error GoTo ErrorHandler
‘ 1. オブジェクトの安全な取得
Set acadPref = ThisDrawing.Application.Preferences.Files
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 2. 現在のサポートパスを取得
rawPaths = acadPref.SupportPath
‘ 3. 社内標準パスの存在確認と配列化
‘ ネットワーク切断時にAutoCADがフリーズするのを防ぐため、物理存在を確認する
standardArray = Split(STANDARD_PATHS, DELIMITER)
Dim validStandardPaths As String
validStandardPaths = “”
For i = LBound(standardArray) To UBound(standardArray)
Dim targetPath As String
targetPath = Trim(standardArray(i))
If targetPath <> “” Then
‘ フォルダが存在するかチェック(ローカルまたは到達可能なUNCパスのみ採用)
If fso.FolderExists(targetPath) Then
If validStandardPaths = “” Then
validStandardPaths = targetPath
Else
validStandardPaths = validStandardPaths & DELIMITER & targetPath
End If
Else
Debug.Print “[Warning] 社内標準パスが見つからないためスキップされました: ” & targetPath
End If
End If
Next i
If validStandardPaths = “” Then
MsgBox “有効な社内標準パスに接続できません。ネットワーク接続を確認してください。”, vbCritical, “同期エラー”
GoTo Cleanup
End If
‘ 4. 既存パスから社内標準パスを除外しつつ、重複のないクリーンなリストを作成
‘ 設計思想: 社内標準パスは常に最新のものを「最優先(先頭)」に配置し、ローカル固有のパスは保持する
pathArray = Split(rawPaths, DELIMITER)
optimizedPaths = validStandardPaths ‘ 先頭に有効な社内標準を配置
isModified = False
For i = LBound(pathArray) To UBound(pathArray)
Dim currentPath As String
currentPath = Trim(pathArray(i))
If currentPath <> “” Then
‘ 既存のパスが社内標準に含まれているかチェック
If Not IsPathInList(currentPath, standardArray) Then
‘ 社内標準に含まれないユーザー独自のパスであれば維持する
If Not IsPathInList(currentPath, Split(optimizedPaths, DELIMITER)) Then
optimizedPaths = optimizedPaths & DELIMITER & currentPath
End If
Else
‘ 順序やパスの表記揺れを正規化するため、変更有りとみなす
isModified = True
End If
End If
Next i
‘ 5. パスの書き込み(変更がある場合、または強制同期が必要な場合のみ実行)
‘ 無駄なレジストリ書き込みを避ける
If acadPref.SupportPath <> optimizedPaths Then
acadPref.SupportPath = optimizedPaths
MsgBox “社内標準のサポートファイルの検索パスが正常に同期されました。”, vbInformation, “環境同期完了”
Else
Debug.Print “[Info] サポートパスの変更はありませんでした。”
End If
Cleanup:
‘ 6. 厳格なメモリ解放(COMオブジェクトのリーク防止)
Set fso = Nothing
Set acadPref = Nothing
Exit Sub
ErrorHandler:
MsgBox “サポートパスの同期中に予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
Resume Cleanup
End Sub
‘================================================================================
‘ 補助関数: 指定されたパスがリスト内に存在するか判定(大文字小文字を区別しない)
‘================================================================================
Private Function IsPathInList(ByVal targetPath As String, ByRef pathList() As String) As Boolean
Dim i As Long
targetPath = NormalizePath(targetPath)
For i = LBound(pathList) To UBound(pathList)
If NormalizePath(pathList(i)) = targetPath Then
IsPathInList = True
Exit Function
End If
Next i
IsPathInList = False
End Function
‘================================================================================
‘ 補助関数: パスの末尾のバックスラッシュ正規化と小文字化
‘================================================================================
Private Function NormalizePath(ByVal pathStr As String) As String
pathStr = Trim(pathStr)
If Right$(pathStr, 1) = “\” Then
pathStr = Left$(pathStr, Len(pathStr) – 1)
End If
NormalizePath = LCase(pathStr)
End Function
—
3. チーフアーキテクトが解説する実装の急所
オブジェクトのライフサイクルとメモリマネジメント
VBAの裏側ではCOM(Component Object Model)が稼働している。`ThisDrawing.Application.Preferences.Files` を呼び出す際、暗黙的にCOMコンポーネントへの参照カウンタがインクリメントされる。
処理の終端で `Set acadPref = Nothing` および `Set fso = Nothing` を明示的に行わない場合、AutoCADのプロセス内に参照が残り続け、ドキュメントを閉じた際のメモリリークや、最悪の場合の AutoCAD 本体のアングレイス(異常終了)を引き起こす。シニアエンジニアであれば、クリーンアップ処理の徹底はプロトコルであるべきだ。
UNCパスとタイムアウト問題の回避
社内サーバー(`\\server\…`)へのパスを扱う際、VPN未接続時やサーバーメンテナンス時に `FolderExists` や AutoCAD 自体がそのパスを評価しようとすると、OSレベルでI/O待ちが発生し、AutoCADが数秒〜数テン秒フリーズする。
上記のコードでは、あらかじめ `Scripting.FileSystemObject` を用いてローカル・ネットワークの生存確認(存在チェック)を行ってから `SupportPath` プロパティへ代入しているため、無効なパスによるフリーズを完全に根絶している。
自動実行のフック(Enterprise Deployment)
このVBAプロシージャを実務で活かすには、手動実行ではなく AutoCADの起動時(`acaddoc.lsp` または `AcadApplication_AppActivate` イベント) にフックさせるべきだ。
企業全体のスタンダードとして強制する場合、ドキュメントオープンイベント(`Workbook_Open` 相当の `AcadDocument_Activate`)に組み込み、サイレントモードで実行することで、エンドユーザーに意識させることなく常に最新の環境を維持し続けることが可能となる。
—
結びにかえて
環境構築の自動化は、単なる「手間の削減」ではない。それは「ヒューマンエラーによる図面品質の揺らぎをシステム的に排除する」というエンジニアリングの本懐である。
レガシーなVBAであっても、オブジェクトモデルの挙動、メモリのライフサイクル、そしてインフラストラクチャの制約を正しく理解していれば、モダンなシステムに匹敵する堅牢なソリューションを構築できる。あなたの設計室のCAD環境を、今すぐこのコードで統制下においてほしい。
