【極限の知見】AutoCADクラッシュからのデータ蘇生:自動リカバリエンジンの設計思想と実装
業務自動化の現場において、最もエンジニアの精神を削る事象は何か。それはバグではない。「不可避なクラッシュによる、数時間の作業データの消失」である。
AutoCADは極めて強力なツールだが、複雑なLISP、重厚な外部参照、あるいはメモリリークを抱えたサードパーティ製アドインが絡み合うとき、プロセスは突如として死に至る。標準の「図面の回復」機能は存在するが、それはユーザーの「手動操作」を前提とした、あまりに受動的な設計だ。
我々プロフェッショナルが構築すべきは、異常終了を検知し、バックグラウンドで「幽霊(Ghost files)」を探索し、もっとも整合性の高い状態へとデータを引き戻す「自動リカバリ・エンジン」である。
本稿では、AutoCADが生成する一時ファイル(`.sv$` / `.ac$`)のライフサイクルを掌握し、Windows APIとVBAを駆使して、失われたデータを確実にサルベージするためのアーキテクチャを解説する。
1. データの死角:AutoCAD一時ファイルの正体
AutoCADがクラッシュした際、メモリ上にあったデータは、ディスク上の「一時ディレクトリ」に書き込まれた `.sv$` (Automatic Save) ファイルの中に断片として残されている。
ここで重要なのは、「最新のファイルが必ずしも復旧に最適とは限らない」という点だ。
クラッシュの直前に、壊れた図面データがオートセーブされてしまった場合、そのファイルを開こうとすれば、リカバリツール自体が連鎖的にクラッシュする「再帰的クラッシュ」を引き起こす。
我々のエンジンには、以下の3つの責務が求められる。
1. Deterministic Path Discovery: 設定に基づいた正確な一時フォルダの特定。
2. Temporal Scavenging: タイムスタンプに基づいた、最新かつ有効なファイルの特定。
3. Safe Resurrection: オブジェクトのライフサイクルを制御した、安全なファイル変換とロード。
2. アーキテクチャの実装:Scavenger Engine
以下に、プロフェッショナル仕様のリカバリ・ロジックを実装したコードを示す。ここでは、単なるファイル操作ではなく、`FileSystemObject` を用いた堅牢な探索と、エラーハンドリングの徹底に重点を置いている。
Implementation: `clsRecoveryEngine` (Class Module)
'-------------------------------------------------------------------------------
' Class: clsRecoveryEngine
' Description: AutoCADクラッシュ後のバックアップファイルを探索・復元する
'-------------------------------------------------------------------------------
Option Explicit
Private m_tempPath As String
Private m_fso As Object ' Scripting.FileSystemObject
' 初期化: AutoCADのTempディレクトリを取得
Private Sub Class_Initialize()
Set m_fso = CreateObject("Scripting.FileSystemObject")
' AutoCADのTempPrefixプロパティからパスを特定する
' Note: 環境によって異なるため、Applicationオブジェクト経由で取得するのが定石
On Error Resume Next
m_tempPath = ThisDrawing.Application.TempPrefix
If m_tempPath = "" Then
' フォールバック: WindowsのTEMP環境変数
m_tempPath = Environ("TEMP") & "\"
End If
On Error GoTo 0
End Sub
' 破棄: メモリ解放の徹底(オブジェクトのライフサイクル管理)
Private Sub Class_Terminate()
Set m_fso = Nothing
End Sub
' メインロジック: 最新の.sv$ファイルを特定し、.dwgとして復元を試みる
Public Function RecoverLatestBackup(ByVal originalFileName As String) As String
Dim folder As Object
Dim file As Object
Dim latestFile As Object
Dim latestDate As Date
Dim targetExtension As String
Dim recoveredPath As String
targetExtension = ".sv$"
latestDate = DateSerial(1900, 1, 1)
' 1. テンポラリディレクトリの存在確認
If Not m_fso.FolderExists(m_tempPath) Then
RecoverLatestBackup = ""
Exit Function
End If
Set folder = m_fso.GetFolder(m_tempPath)
' 2. Scavenging: ファイルの探索とタイムスタンプ比較
' 高速化のため、FileSystemObjectのイテレータを使用
For Each file In folder.Files
' ファイル名に元のファイル名が含まれており、かつ拡張子が.sv$であるものを対象とする
' 例: "Project_A.dwg" -> "Project_A_1_1234.sv$"
If InStr(1, file.Name, m_fso.GetBaseName(originalFileName), vbTextCompare) > 0 And _
LCase(m_fso.GetExtensionName(file.Name)) = "sv$" Then
If file.DateLastModified > latestDate Then
latestDate = file.DateLastModified
Set latestFile = file
End If
End If
Next file
' 3. Resurrection: ファイルの変換と保存
If Not latestFile Is Nothing Then
' 復元パスの生成 (.sv$ -> .dwg)
recoveredPath = m_fso.GetParentFolderName(originalFileName) & "\" & _
m_fso.GetBaseName(latestFile.Name) & "_Recovered.dwg"
On Error GoTo ErrorHandler
' ファイルのコピー(元の.sv$を汚さないための作法)
m_fso.CopyFile latestFile.Path, recoveredPath, True
RecoverLatestBackup = recoveredPath
Exit Function
End If
ErrorHandler:
' ロギングの実装を推奨(本例では簡略化)
Debug.Print "Critical Error during recovery: " & Err.Description
RecoverLatestBackup = ""
End Function
利用側(Standard Module)の実装例
Sub RunEmergencyRecovery()
Dim engine As clsRecoveryEngine
Dim targetFile As String
Dim recoveredFile As String
' 対象となる(失われた可能性のある)ファイルパス
targetFile = "C:\Projects\Critical_Design.dwg"
Set engine = New clsRecoveryEngine
Debug.Print "Initiating Scavenging Process..."
recoveredFile = engine.RecoverLatestBackup(targetFile)
If recoveredFile <> "" Then
MsgBox "Recovery Successful!" & vbCrLf & "File: " & recoveredFile, vbInformation
' ここで、復元したファイルを新しいドキュメントとして開く
' 注意: Openメソッドはクラッシュのリスクを伴うため、Try-Catch的な制御が必要
Documents.Open recoveredFile
Else
MsgBox "No valid backup found in temp directory.", vbExclamation
End If
' 明示的な解放
Set engine = Nothing
End Sub
3. エンジニアリングの極致:パフォーマンスと安定性のための注意点
このコードを実戦投入するにあたり、シニアエンジニアが留意すべき「重み」が3点ある。
① オブジェクトのライフサイクル(Memory Management)
VBAにおいて、`Set obj = Nothing` は単なる作法ではない。特にAutoCADのような巨大なCOMオブジェクトを扱う場合、参照カウントが適切にデクリメントされないと、プロセスのゾンビ化(AutoCADが終了しているのに `acad.exe` がタスクマネージャーに残る現象)を引き起こす。`clsRecoveryEngine` 内で `FileSystemObject` をクラス変数として保持し、`Class_Terminate` で確実に解放する設計は、このリスクを最小化するための必須要件である。
② I/O パフォーマンスとFileSystemObject
大量のファイルが溜まったテンポラリフォルダにおいて、`Dir()` 関数によるループは高速だが、メタデータ(作成日時など)の取得において、VBAの標準関数では限界がある。`Scripting.FileSystemObject` を用いることで、OSレベルのファイル属性へのアクセスを安定させ、正確なタイムスタンプ判定を可能にしている。
③ 再帰的クラッシュの回避(Defensive Programming)
復元した `.dwg` を開く際、そのファイル自体が破損している場合、`Documents.Open` を実行した瞬間にVBAエディタごとクラッシュする。
これを防ぐには、AutoCADのメインプロセスとは別に、「検証用プロセス(Lightweight AutoCAD instance)」をVBAから起動し、そこでファイルが正常に開けるかを確認してからメインプロセスへ渡す、という極めて堅牢な多層防御アーキテクチャを検討すべきである。
結言
データの復旧は、単なるファイルのコピーではない。それは、システムの「不完全性」を、エンジニアの「設計」によって補完する行為である。
今回提示したリカバリ・エンジンは、そのための最小単位である。これをベースに、ログ出力、エラー通知、さらには破損検知アルゴリズムを組み込むことで、あなたの設計した自動化システムは、単なる「ツール」から、信頼に足る「インフラ」へと昇華するだろう。
設計に妥協は許されない。データに慈悲はない。
