クラウドストレージの罠を突破せよ:AutoCAD VBAによるOneDrive/SharePoint同期制御の極致
AutoCADのオートメーションにおいて、ローカルファイルとクラウド同期フォルダの境界は、かつてない不安定さをシステムにもたらしている。OneDriveやSharePointがバックグラウンドで走らせる「差分同期」は、我々が設計したVBAの堅牢なパイプラインをいとも簡単に破壊する。
「ファイルは存在するのに開けない」「保存直後に同期競合が発生し、図面が破損した」。これらは単なるエラーではない。同期エンジンとAutoCADという、二つの巨大な非同期プロセスの調停に失敗している証左だ。
本稿では、レガシーなAutoCAD VBAをクラウド時代の最適解へと引き上げるための、非同期制御の真髄を説く。
—
1. 同期遅延を「エラー」ではなく「ステート」として扱う
標準の`Documents.Open`メソッドをそのまま叩くのは、時速100kmで走行中にタイヤを交換するようなものだ。まずは、ファイルが「排他制御下にあるか」を判定するのではなく、「同期エンジンがそのファイルを握っているか」を判定しなければならない。
Windows APIの`CreateFile`を用いて、`GENERIC_WRITE`権限でのオープンを試みることで、同期中(ファイルロック中)のファイルを即座に検知する。
‘ Windows API: ファイルの排他権を獲得し、同期中のロック状態を判定する
Private Declare PtrSafe Function CreateFile Lib “kernel32” Alias “CreateFileA” ( _
ByVal lpFileName As String, ByVal dwDesiredAccess As Long, _
ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, _
ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, _
ByVal hTemplateFile As Long) As LongPtr
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_EXISTING = 3
Private Const INVALID_HANDLE_VALUE = -1
‘ 指定したファイルがクラウド同期等でロックされているか確認
Public Function IsFileLocked(ByVal filePath As String) As Boolean
Dim hFile As LongPtr
hFile = CreateFile(filePath, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
If hFile = INVALID_HANDLE_VALUE Then
IsFileLocked = True ‘ ロックされている
Else
CloseHandle hFile
IsFileLocked = False
End If
End Function
2. 再帰的な待機アルゴリズム(Exponential Backoff)
単純な`Sleep`関数での待機は、システムのパフォーマンスを殺す愚策だ。同期が完了するまで指数関数的に待機時間を延ばす「エクスポネンシャル・バックオフ」を実装し、AutoCADのメインスレッドをフリーズさせない工夫が必要となる。
Public Function OpenDrawingSafe(ByVal filePath As String) As AcadDocument
Dim retryCount As Integer
Dim delay As Long
delay = 500 ‘ 初回待機 500ms
Do While IsFileLocked(filePath) And retryCount < 10 DoEvents ' UIスレッドを維持 Sleep delay delay = delay 2 ' 待機時間を倍増させる retryCount = retryCount + 1 Loop If retryCount >= 10 Then Err.Raise vbObjectError + 1001, , “同期待ちタイムアウト”
Set OpenDrawingSafe = ThisDrawing.Application.Documents.Open(filePath)
End Function
3. メモリ管理とオブジェクトのライフサイクル
VBAにおける最大の盲点は、`AcadDocument`や`AcadDatabase`オブジェクトの解放漏れだ。特にクラウドストレージ経由の操作では、COM参照がゾンビ化しやすい。
極限の安定性を追求するなら、処理の最後には必ず`Close`メソッドを呼び出し、明示的に`Nothing`を代入するだけでなく、ガベージコレクションを促すためにスコープを細分化せよ。
- Documentオブジェクトをグローバル変数に置くな: 必要最小限のスコープで宣言し、プロシージャ終了時に確実に破棄する。
- `AcadApplication.ActiveDocument`への依存を避ける: 複数の図面を扱う際は、必ず戻り値として受け取ったオブジェクトを操作する。
4. システム間連携における「メタデータ」活用
SharePointと連携する場合、AutoCADのファイル属性だけでは不十分だ。同期状態はWindowsのファイルシステム属性(`GetFileAttributes`)にも現れる。`FILE_ATTRIBUTE_OFFLINE`をチェックすることで、クラウド上にしか存在しない「プレースホルダーファイル」を事前に検知し、強制的にダウンロード(同期)をトリガーするAPI呼び出しを先行させるのが、プロフェッショナルの作法である。
—
最後に:自動化の先にある「信頼」
我々が書くコードは、単に図面を開くための文字列ではない。それは、クラウドという変動する大地の上に築かれる、確固たるインフラである。
同期遅延によるエラーを「マシンのせい」にしてはいけない。それは、貴方のシステムが「同期中」という状態を正しくハンドリングできていないという設計上の敗北だ。
今回紹介したAPIによる排他制御と指数バックオフは、その第一歩に過ぎない。この構造をマスターすれば、どんなに劣悪なネットワーク環境下であっても、貴方のAutoCAD自動化システムは沈黙することなく、淡々と業務を完遂するはずだ。
次は、図面データベース内のオブジェクトの生存期間と、クラウド同期の衝突による「図面破損」を未然に防ぐ、トランザクション・ログの実装について深掘りすることにしよう。
