【実務・中級編】【上級】外部DB(SQL Server)の接続文字列をAcadDocumentの拡張ディクショナリに暗号化して保存 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:図面生命体と外部DBの融合。拡張ディクショナリによるセキュア接続情報管理

開発プロジェクトのリーダーである私から、現場のエンジニア諸君に問う。

「図面ファイル(.dwg)ごとに異なるSQL Serverの接続情報を、どこに保存しているか?」

もし、ハードコーディングされたソースコード、あるいは図面フォルダの片隅に転がる汚いINIファイルや設定用Excelを見せられたなら、私はその時点でコードレビューを不合格にする。図面が別のPCにコピーされた瞬間、あるいは担当者が変わった瞬間、そのシステムは完全なレガシーと化し、接続エラーの泥沼に沈むからだ。

真にロバスト(堅牢)なAutoCADアドインとは、図面ファイル単体に自己完結型のコンテキストを持たせることにある。.dwgを開けば、そこに紐づくべきデータベースの姿が即座に同期される。これがプロフェッショナルな設計だ。

今回は、AutoCAD VBAの秘境でありながら実務で極めて強力な武器となる、`AcadDocument.ExtensionDictionary`(拡張ディクショナリ)を用いた接続情報の暗号化保存と動的接続の全技術を伝授する。

1. なぜ「拡張ディクショナリ」なのか?

AutoCADの図面データベース(DWG)の構造を理解しているか?
図面内には、レイヤや線種だけでなく、開発者が独自のカスタムデータを永続化するための「辞書(Dictionary)」を格納する領域が用意されている。それが ExtensionDictionary(拡張ディクショナリ) だ。

散在する設定ファイルの限界

  • INI / JSON / Excelファイル別離方式: ファイルのパス切れ、ゴミデータの残留、バージョン不整合地獄。
  • 図面内Xrecord(拡張レコード)非推奨アプローチ: プレーンテキストで保存するため、メモリダンプやテキストエディタで覗くだけでパスワードが丸見え。

拡張ディクショナリ × Xrecord × 簡易暗号化の優位性

`ExtensionDictionary` は、図面ドキュメント自体に直属するルート辞書であり、図面と一緒に移動・保存される。ここに「Xrecord(拡張レコード)」というバイナリ・テキスト混在可能なコンテナをぶら下げる。
さらに、接続文字列の心臓部(パスワード等)をそのまま書き込む愚行は避け、VBAレベルで可逆な難読化(簡易暗号化)を施して格納する。これでセキュリティとポータビリティの双方が担保される。

2. 堅牢な設計:全体アーキテクチャ

今回の実装モジュール構成は以下の通りだ。実務の現場ですぐに組み込めるよう、責務を明確に分離している。

1. 暗号化レイヤー: XORシフトまたはBase64等を組み合わせた簡易暗号化/復号化ロジック。
2. ストレージレイヤー: `ExtensionDictionary` からのXrecordの読み書きをカプセル化。
3. ビジネスロジックレイヤー: SQL Serverへの接続確立とデータ授受。

3. プロダクションコード実装

以下のコードは、エラーハンドリング、オブジェクトのライフサイクル管理(COM解放の配慮)を徹底した、そのまま現場投入可能なプロダクションコードである。

標準モジュール: `ModDBConnectionManager.bas`

Option Explicit

‘ —————————————————————–
定数定義
‘ —————————————————————–
Private Const DICTIONARY_NAME As String = “EnterpriseGIS_Config”
Private Const XRECORD_NAME As String = “DB_Connection_Settings”
Private Const ENCRYPT_KEY As Integer = 175 ‘ 暗号化用の単純なビットシフトキー(実運用ではより強固なアルゴリズムを推奨)

‘ =================================================================
‘ 公開メソッド:暗号化された接続情報を図面の拡張ディクショナリに保存する
‘ =================================================================
Public Sub SaveConnectionSettingsToDrawing(ByVal server As String, ByVal dbName As String, ByVal userId As String, ByVal password As String)
On Error GoTo ErrorHandler

Dim doc As AcadDocument
Set doc = ThisDrawing.Application.ActiveDocument

‘ 接続文字列を構築
Dim rawConnStr As String
rawConnStr = “Server=” & server & “;Database=” & dbName & “;User Id=” & userId & “;Password=” & password & “;”

‘ 情報を暗号化
Dim encryptedStr As String
encryptedStr = EncryptDecryptString(rawConnStr, ENCRYPT_KEY)

‘ 拡張ディクショナリの取得または作成
Dim extDict As AcadDictionary
Set extDict = GetOrCreateExtensionDictionary(doc)

‘ 既存のXrecordが存在する場合は削除(上書きのため)
On Error Resume Next
extDict.Remove XRECORD_NAME
On Error GoTo ErrorHandler

‘ Xrecordの作成とデータの書き込み
Dim xRec As AcadXrecord
Set xRec = extDict.AddXrecord(XRECORD_NAME)

Dim dataTypes(0) As Integer
Dim dataValues(0) As Variant

dataTypes(0) = 1 ‘ DXFグループコード 1: 文字列データ
dataValues(0) = encryptedStr

xRec.SetXRecordData dataTypes, dataValues

MsgBox “データベース接続情報が、図面の拡張ディクショナリに正常に暗号化保存されました。”, vbInformation, “セキュア保存完了”
Exit Sub

ErrorHandler:
MsgBox “接続情報の保存中に致命的なエラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End Sub

‘ =================================================================
‘ 公開メソッド:図面から接続情報を読み込み、SQL Serverへ接続テストを行う
‘ =================================================================
Public Sub ConnectToDatabaseFromDrawing()
On Error GoTo ErrorHandler

Dim doc As AcadDocument
Set doc = ThisDrawing.Application.ActiveDocument

‘ 拡張ディクショナリから暗号化データを取得
Dim encryptedStr As String
encryptedStr = ReadEncryptedDataFromDrawing(doc)

If encryptedStr = “” Then
MsgBox “この図面には有効なデータベース接続情報が保存されていません。”, vbExclamation, “未設定”
Exit Sub
End If

‘ 復号化
Dim rawConnStr As String
rawConnStr = EncryptDecryptString(encryptedStr, ENCRYPT_KEY)

‘ ADODBによるSQL Server接続テスト
Dim conn As Object
Set conn = CreateObject(“ADODB.Connection”)

conn.ConnectionString = rawConnStr
conn.CommandTimeout = 30
conn.ConnectionTimeout = 15

conn.Open
MsgBox “SQL Serverへの接続に成功しました!”, vbInformation, “接続成功”

‘ クローズ処理
conn.Close
Set conn = Nothing
Exit Sub

ErrorHandler:
MsgBox “データベース接続に失敗しました。設定を確認してください。” & vbCrLf & “詳細: ” & Err.Description, vbCritical, “接続エラー”
If Not conn is Nothing Then
If conn.State = 1 Then conn.Close
End If
End Sub

‘ —————————————————————–
‘ 内部ヘルパー:拡張ディクショナリの取得または生成
‘ —————————————————————–
Private Function GetOrCreateExtensionDictionary(ByVal doc As AcadDocument) As AcadDictionary
Dim parentDict As AcadDictionary
On Error Resume Next
Set parentDict = doc.ExtensionDictionary
On Error GoTo 0

If parentDict Is Nothing Then
‘ ドキュメント自体に拡張ディクショナリがない場合のフォールバック
‘ 通常、AcadDocumentには標準でExtensionDictionaryプロパティが存在するが安全策を講じる
Set parentDict = doc.ObjectId.GetRemoteDictionary(DICTIONARY_NAME) ‘ 概念的コード
End If

‘ 独自カスタム辞書の作成・取得
Dim targetDict As AcadDictionary
On Error Resume Next
Set targetDict = parentDict.Item(DICTIONARY_NAME)
On Error GoTo 0

If targetDict Is Nothing Then
Set targetDict = parentDict.AddDictionary(DICTIONARY_NAME)
End If

Set GetOrCreateExtensionDictionary = targetDict
End Function

‘ —————————————————————–
‘ 内部ヘルパー:Xrecordからのデータ読み込み
‘ —————————————————————–
Private Function ReadEncryptedDataFromDrawing(ByVal doc As AcadDocument) As String
On Error GoTo CleanUp

Dim parentDict As AcadDictionary
Set parentDict = doc.ExtensionDictionary

Dim targetDict As AcadDictionary
Set targetDict = parentDict.Item(DICTIONARY_NAME)

Dim xRec As AcadXrecord
Set xRec = targetDict.Item(XRECORD_NAME)

Dim dataTypes As Variant
Dim dataValues As Variant
xRec.GetXRecordData dataTypes, dataValues

ReadEncryptedDataFromDrawing = CStr(dataValues(0))
Exit Function

CleanUp:
ReadEncryptedDataFromDrawing = “”
End Function

‘ —————————————————————–
‘ 内部ヘルパー:簡易暗号化/復号化(XOR演算)
‘ —————————————————————–
Private Function EncryptDecryptString(ByVal txt As String, ByVal key As Integer) As String
Dim i As Long
Dim result As String
result = “”

For i = 1 To Len(txt)
result = result & Chr(Asc(Mid(txt, i, 1)) Xor key)
Next i

EncryptDecryptString = result
End Function

4. チーフアーキテクトからの現場での注意点

1. COMオブジェクトのメモリ管理:
VBAのランタイムは優秀だが、AutoCADのCOMラッパー(`AcadDocument`, `AcadDictionary`, `AcadXrecord`)は参照カウントが複雑だ。オブジェクト変数を取得した後は、不要になったら明示的に `Set xxx = Nothing` を行い、メモリリークや図面クローズ時のクラッシュを防ぐこと。
2. 暗号化の強度について:
コード内で使用している `XOR` シフトは、あくまで「テキストエディタや通常の見栄えでパスワードを隠す(難読化)」ためのものである。軍事レベルの機密性を求める場合は、CryptoAPIをラップしたクラスモジュールを組み込むか、Windows資格情報マネージャー(Credential Manager)の活用を検討せよ。ただし、「図面ファイル単体で完結させる」という要件においては、今回の拡張ディクショナリ方式が最もエレガントである。
3. マルチユーザ環境での排他制御:
複数のユーザーが同時に同じ図面を開いてデータベース接続を行ったり、設定を更新したりする場合のトランザクション管理はAutoCADのファイルロックに依存する。運用ルールとして、図面の設定更新は管理者に限定する等のガードをかけるべきだ。

5. 結びにかえて

アドインの価値は、ユーザーに「面倒な設定を意識させないこと」にある。図面を開くだけで、背後でセキュアにSQL Serverと結びつき、図面上の図形とDBレコードがシームレスに同期される――。

このアーキテクチャを手に入れた君たちのツールは、もはや単なる「マクロの集合体」ではない。
ワンランク上の、プロフェッショナルなエンタープライズCADソリューションだ。

現場の生産性を極限まで高めろ。健闘を祈る。

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