VBScriptを極める:ファイル同期における「タイムスタンプ衝突」の完全制御と安全退避ロジック
VBScriptという言語は、現代のクラウドネイティブな開発環境から見れば「化石」のように見えるかもしれない。しかし、製造業の現場や堅牢性が求められるレガシーなオンプレミス環境において、これほど低レイテンシでWindows OSの深層に直結できるツールは他にない。
今日論じるのは、ただのファイルコピーではない。「双方向同期におけるタイムスタンプ衝突」という、分散システムにおける最も厄介な事象を、いかにFSO(FileSystemObject)で安全に処理するかという極限の知見だ。
1. 衝突検知の設計思想:なぜ「上書き」が許されないのか
同期エンジンにおいて、A地点とB地点の両方でファイルが更新された場合、単純なタイムスタンプ比較では「後勝ち」になる。しかし、どちらの変更も捨てられないビジネス要件がある場合、それはデータ損失(ロスト)を意味する。
真のプロフェッショナルが実装すべきは、以下の3ステップだ。
1. メタデータ比較: `DateLastModified` を比較するが、絶対値で判断しない。
2. 衝突判定: 両方のタイムスタンプが「基準時刻(前回の同期時刻)」より新しい場合、それは「衝突」とみなす。
3. アトミックな退避: 競合したファイルを削除せず、タイムスタンプを付与した別名で保存する。
2. 衝突解決ロジックの実装(VBScript)
以下のコードは、単なるスクリプトではない。メモリ管理とオブジェクトのライフサイクルを考慮した、現場仕様のエンジンだ。
‘ — 極限のファイル同期ロジック: 衝突検知エンジン —
Option Explicit
Dim fso, folderA, folderB
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ メモリ最適化: オブジェクトを必要最小限のスコープで扱う
‘ 大量ファイル処理時は、各ファイル処理後に明示的なNothing代入を行うこと
Sub SynchronizeFiles(pathA, pathB, lastSyncTime)
Dim fileA, fileB, targetPath
Set folderA = fso.GetFolder(pathA)
For Each fileA In folderA.Files
If fso.FileExists(pathB & “\” & fileA.Name) Then
Set fileB = fso.GetFile(pathB & “\” & fileA.Name)
‘ 衝突検知: 両ファイルが最終同期時刻より後に更新されているか
If fileA.DateLastModified > lastSyncTime And fileB.DateLastModified > lastSyncTime Then
Call HandleCollision(fileA, fileB)
ElseIf fileA.DateLastModified > fileB.DateLastModified Then
fileA.Copy fileB.Path, True
End If
Set fileB = Nothing
End If
Next
‘ メモリ解放の徹底
Set folderA = Nothing
End Sub
Sub HandleCollision(fA, fB)
Dim timestamp
‘ タイムスタンプをリネーム用の文字列に変換 (YYYYMMDDHHMMSS)
timestamp = Year(Now) & Right(“0” & Month(Now), 2) & Right(“0” & Day(Now), 2) & _
Right(“0” & Hour(Now), 2) & Right(“0” & Minute(Now), 2)
‘ 安全退避: 衝突したファイルAを別名で保存
fA.Copy fB.ParentFolder.Path & “\” & fA.Name & “.CONFLICT_” & timestamp, False
‘ ログ記録: 監査証跡を残すことはエンジニアの責務
WScript.Echo “CONFLICT DETECTED: ” & fA.Name & ” at ” & Now
End Sub
3. なぜこの設計が必要なのか(アーキテクトの視点)
オブジェクトのメモリ管理
VBScriptのエンジンである `wscript.exe` は、長時間のループ処理においてメモリリークが発生しやすい。特に `FileSystemObject` は、ループ内でインスタンスを乱造するとスタックを圧迫する。常に `Set obj = Nothing` でデストラクタを明示的に呼び出す癖をつけろ。
ファイルシステムの「揺らぎ」を吸収する
ファイルシステムは、ネットワークドライブ経由の場合、タイムスタンプの精度に「誤差(Clock Skew)」が生じることがある。厳密な同期を行うなら、FSOの `DateLastModified` だけでなく、Win32 APIの `GetFileTime` を呼び出し、ナノ秒単位での比較を行う実装も視野に入れるべきだ。
ログの重要性
衝突時にファイルを退避させる際、必ず「なぜ衝突したか」というメタデータ(または同期元情報)をログに書き出せ。管理者が後から「あのファイルはどこへ消えた?」と問う事態を未然に防ぐのが、アーキテクトの仕事である。
4. 結び:レガシーを「保守」ではなく「昇華」させる
VBScriptを使い続けることは、決して古いことではない。OSの深層に触れ、メモリの挙動を制御し、競合という不確実性に論理で立ち向かう。このプロセスこそが、エンジニアとしての基礎体力を養う。
もし君が現在、大規模な同期システムの崩壊に悩んでいるのなら、まずはこの「衝突検知リネーム」を導入することから始めよ。エラーを隠蔽せず、「衝突を可視化する」ことこそが、システムを堅牢にする唯一の近道だ。
コードは嘘をつかない。君が書いたロジックが、システムを静かに、そして確実に守り抜くことを期待している。
