【テクニカル・上級編】【上級プロフェッショナル向け】ネットワーク切断時の緊急退避保存:保存失敗をトラップしてローカルへ自動バックアップ – AutoCAD VBA解析バイブル

スポンサーリンク

ネットワークの瞬断を「絶望」に変えない:AutoCAD VBAにおける緊急退避保存の極致

設計業務の最前線において、ネットワークストレージへの直接保存は常にリスクを孕んでいる。VPNの瞬断、SMBプロトコルのタイムアウト、サーバー側の排他制御エラー。これらが重なった瞬間、数時間の成果が虚空へと消える。

一般的な開発者は「保存に失敗しました」というダイアログを表示して終わるだろう。しかし、我々プロフェッショナルは、ユーザーがそのメッセージを目にする前に、メモリ上のデータをローカルの「安全地帯」へ強制的に退避させる回路を組み込んでおくべきだ。

本稿では、AutoCAD VBAを用いた「ネットワーク切断時の緊急自動バックアップ・スキーム」の実装について、Windows APIの深淵からオブジェクトのライフサイクル管理に至るまでを詳述する。

—

1. なぜ「通常のSave」では不十分なのか

AutoCADの `ThisDrawing.Save` メソッドは、ファイルポインタがネットワーク上にある場合、OSレベルの書き込み遅延や接続断に対して極めて脆弱だ。特に、一度ファイルが「読み取り専用」と誤認されると、VBA側からの制御はロックされ、そのまま異常終了を待つだけの状態(ハングアップ)に陥ることが多い。

我々が実装すべきは、書き込み失敗を検知した瞬間にI/Oのターゲットをローカルストレージへ動的に切り替えるロジックである。

—

2. Windows APIによる「確実な」テンポラリパスの取得

AutoCADの環境変数 `TEMP` を参照するだけでは不十分だ。ユーザー権限や環境の不整合に左右されないよう、Windows API (`kernel32`) を直接叩き、OSが保証する一時フォルダパスを確保する。

If VBA7 Then
‘ 64bit環境(現代のAutoCAD)に対応
Private Declare PtrSafe Function GetTempPath Lib “kernel32” Alias “GetTempPathA” ( _
ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
Else
‘ 32bit互換(レガシー環境用)
Private Declare Function GetTempPath Lib “kernel32” Alias “GetTempPathA” ( _
ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
End If

”’

”’ システムの一時フォルダパスを取得する
”’

Private Function GetSystemTempPath() As String
Dim strBuffer As String
Dim lngRet As Long
strBuffer = String$(260, 0)
lngRet = GetTempPath(260, strBuffer)
If lngRet > 0 Then
GetSystemTempPath = Left$(strBuffer, lngRet)
Else
GetSystemTempPath = “C:\Temp\” ‘ フォールバック
End If
End Function

—

3. 実装:エラートラップと緊急退避のコアロジック

肝要なのは、`SaveAs` メソッドの挙動を完全に制御することだ。ネットワークエラー(エラー番号: -2145320851等)を捕捉した際、即座にファイル名をタイムスタンプ付きの緊急用名称に変更し、ローカルに書き出す。

Public Sub RobustSave()
Dim doc As AcadDocument
Set doc = ThisDrawing.Application.ActiveDocument

‘ 1. ドキュメントの状態チェック
If doc.ReadOnly Then
MsgBox “この図面は読み取り専用です。別名で保存してください。”, vbExclamation
Exit Sub
End If

On Error GoTo ErrorHandler

‘ 2. 通常の保存を試行
‘ ネットワーク上のパスであれば、ここでI/Oエラーが発生する可能性がある
doc.Save
Debug.Print “Normal Save Completed: ” & Now
Exit Sub

ErrorHandler:
‘ 3. エラーハンドリング:保存失敗時の緊急退避
Dim errNumber As Long: errNumber = Err.Number
Dim errDesc As String: errDesc = Err.Description

‘ ネットワーク断、書き込み権限エラー等を想定
If errNumber <> 0 Then
Call EmergencyEvacuation(doc, errNumber, errDesc)
End If
Resume Next
End Sub

Private Sub EmergencyEvacuation(ByRef doc As AcadDocument, ByVal errNum As Long, ByVal errD As String)
On Error Resume Next ‘ 緊急退避処理自体でのクラッシュを回避

Dim localPath As String
Dim fileName As String
Dim fullPath As String
Dim timeStamp As String

‘ タイムスタンプ生成(ファイル名に使用不能な文字を排除)
timeStamp = Format(Now, “yyyyMMdd_HHmmss”)

‘ 保存パスの構築
‘ 元のファイル名から拡張子を除き、ローカルの一時フォルダへ向ける
fileName = “EMERGENCY_” & timeStamp & “_” & doc.Name
If InStr(fileName, “.dwg”) = 0 Then fileName = fileName & “.dwg”

localPath = GetSystemTempPath()
fullPath = localPath & fileName

‘ 4. 緊急SaveAsの実行
‘ ac2018(v24)形式をデフォルトとするが、必要に応じてacNativeを指定
doc.SaveAs fullPath, ac2018_dwg

If Err.Number = 0 Then
Dim msg As String
msg = “【警告】ネットワーク保存に失敗しました。” & vbCrLf & _
“エラー: ” & errD & vbCrLf & vbCrLf & _
“データはローカルに退避されました。直ちに確認してください:” & vbCrLf & _
fullPath
MsgBox msg, vbCritical, “緊急データ保護システム”
Else
MsgBox “致命的エラー:ローカルへの緊急保存にも失敗しました。メモリが破損している可能性があります。”, vbCritical
End If
End Sub

—

4. 専門家としての知見:メモリとリソースの管理

このコードを実戦投入する際、シニアエンジニアが考慮すべき「裏側」の挙動が3つある。

A. DocumentLockMode の制御

AutoCADがコマンド実行中(LISPや他のコマンドが動いている最中)にこのVBAが走る場合、`DocumentLockMode` の不整合で `SaveAs` が拒否されることがある。この場合、`SendCommand` を介して強制的に保存コマンドを投げるか、COMインターフェースを介したドキュメントロックの取得が必要になるが、VBA単体では `ThisDrawing.StartUndoMark` などを適切に配置し、トランザクションを整理しておくことが最善の策だ。

B. オブジェクトの明示的解放

緊急退避後は、速やかにネットワーク上のゾンビファイルポインタを切り離す必要がある。
`Set doc = Nothing` を行うのは当然だが、`SaveAs` 後は `doc.FullName` がローカルパスに書き換わっている点に注意せよ。元のネットワーク上のパスに戻すには、再度ネットワークが復旧した後に `SaveAs` をやり直す必要がある。

C. 保存形式(DWG Version)の動的指定

上記コードでは `ac2018_dwg` を指定している。しかし、社内標準が ac2013 等の旧バージョンの場合、緊急退避先もそれに合わせるべきだ。`doc.GetVariable(“DWGCHECK”)` や `ACADVER` を参照して、現在の図面がどの世代のデータベース構造を持っているかを判定するロジックを組み込むのが一流の仕事である。

—

5. 結論:堅牢性は「想像力」の欠如を補う

「ネットワークは常に繋がっているものだ」という幻想を捨てたとき、初めてプロフェッショナルなツールが完成する。この緊急退避ロジックは、1,000回に1回しか動かないかもしれない。しかし、その1回が、数千万規模のプロジェクトのデッドラインを救うことになる。

我々アーキテクトが書くべきは、単に動くコードではない。「最悪の事態においても、ユーザーの資産を死守するコード」である。この思想を、あなたのシステムにも組み込んでいただきたい。

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