【テクニカル・上級編】【上級プロフェッショナル向け】Dropbox/OneDrive等のクラウドストレージ同期状態を考慮したセーブ待機ロジック – AutoCAD VBA解析バイブル

スポンサーリンク

クラウド同期の「不可視の壁」を突破せよ:AutoCAD VBAにおける同期待機アーキテクチャの極意

AutoCADの自動化において、`ThisDrawing.SaveAs` を実行した瞬間にタスクが終了したと考えるのは、素人の慢心だ。

現代の設計環境において、図面ファイルはローカルに存在しない。OneDriveやDropboxといったクラウドストレージの同期エンジンが、バックグラウンドで絶えずファイルに噛み付いている。特にAutoCADのセーブ処理直後、同期エンジンによるファイルロック(またはメタデータ更新)と、VBAによる次の操作(Closeや他システムへのファイル移動)が競合し、「ファイルは現在使用中です」という悪夢のランタイムエラーを引き起こす。

本稿では、レガシーなVBA環境からクラウド同期の挙動を制御し、極限まで堅牢なワークフローを構築するための戦略を伝授する。

—

1. なぜ「待機」が必要なのか:同期プロトコルの現実

同期エンジンは、ファイルが閉じられた(あるいは保存された)瞬間に「変更分」のハッシュ計算を開始する。このプロセス中、ファイルハンドルは一時的にロックされるか、あるいは「一時的な不整合状態」に陥る。

単なる `Sleep` 関数での待機は、ファイルサイズが数MBから数百MBに及ぶ現代のDWGにおいては非効率極まりない。我々が求めるのは、「ファイルがOSの排他制御下から解放され、かつ同期エンジンの保持するハンドルがクリアされた状態」の確定である。

2. 実装の核心:Win32 APIによるファイルロック監視

`Dir()` 関数や `Scripting.FileSystemObject` では不十分だ。我々はWindows APIを用い、低レイヤーでファイルのオープンを試みることで、ロックの有無を物理的に判定する。

以下のコードは、対象ファイルに対して排他アクセスを試し、成功するまで待機する堅牢なロジックである。

If VBA7 Then
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 Declare PtrSafe Function CloseHandle Lib “kernel32” (ByVal hObject As LongPtr) As Long
Else
Private Declare Function CreateFile Lib “kernel32” Alias “CreateFileA” (…)
Private Declare Function CloseHandle Lib “kernel32” (ByVal hObject As Long) As Long
End If

‘ ファイルが同期エンジン等にロックされていないか確認する関数
Public Function IsFileAvailable(ByVal filePath As String) As Boolean
Dim hFile As LongPtr
‘ GENERIC_READで開き、FILE_SHARE_NONE(排他アクセス)でロック確認を行う
hFile = CreateFile(filePath, &H80000000, 0, 0, 3, &H80, 0)

If hFile <> -1 Then
CloseHandle hFile
IsFileAvailable = True
Else
IsFileAvailable = False
End If
End Function

‘ タイムアウト付きの待機ループ(最大30秒)
Public Sub WaitForSync(ByVal filePath As String)
Dim startTime As Single
startTime = Timer
Do While Not IsFileAvailable(filePath)
DoEvents
If Timer – startTime > 30 Then Err.Raise 999, , “同期待機タイムアウト”
Sleep 500 ‘ 500msのポーリング間隔
Loop
End Sub

3. オブジェクトライフサイクルとメモリ最適化の掟

VBAのメモリ管理は、自動ガベージコレクションに依存している。しかし、AutoCADの `AcadDocument` オブジェクトを扱う際は、明示的な解放(Nothing代入)を怠ってはならない。

特に、同期監視中にループを回す際、ループ内で一時的なオブジェクト生成を行えば、メモリリークは確実に発生する。以下の鉄則を守れ:

  • 循環参照の回避: `ThisDrawing` を多用せず、`ActiveDocument` をローカル変数にキャッシュして操作する。
  • イベントの切断: 長時間の同期待機中、AutoCADのイベント(`BeginSave`等)が発火して予期せぬ再帰呼び出しを招かないよう、監視中は必要に応じてイベントリスナーを一時的に無効化する。

4. シニアエンジニアへの提言:設計の抽象化

クラウド同期の問題は、単なる「待ち時間の問題」ではない。これは分散システムにおける「整合性制御」の問題である。

もし貴方のシステムが、複数の設計者が同時に触る環境にあるのであれば、VBA単体での解決には限界がある。
1. 同期済みの別名保存: 一度ローカルの Temp フォルダに保存し、同期エンジンが感知しないタイミングで正式なクラウドパスへ `MoveFile` APIを用いてアトミックに移動させる。
2. ログによるトレース: 同期失敗が多発する環境では、VBAから「同期完了待ち」のログをテキストファイルに出力し、別プロセスの監視エージェント(VB.NETなどで作成した常駐アプリ)で同期状況を管理させる。

結びに代えて

技術とは、魔法ではない。ハードウェアの限界と、OSのファイルシステム、そしてネットワークの遅延という「物理的な制約」と向き合うことこそが、真の自動化エンジニアの仕事である。

「なぜかたまに失敗する」という曖昧な挙動を、APIを駆使して「100%の確定事象」へと昇華させる。その一歩先に、本当の意味での自動化がある。諸君のコードが、過酷なクラウド環境下でも沈黙を守り、確実にタスクを完遂することを期待している。

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