VBScriptを極めし者へ:排他ロックの壁を「VSS」で突破する深淵のテクニック
システム運用という戦場において、最も忌むべき存在は「排他ロック」だ。データベースファイル、稼働中のログ、あるいはバックアップを拒む頑固なプロセス。`Scripting.FileSystemObject`(以下FSO)を頼りに設計されたスクリプトが、`Permission Denied (800A0046)`という無慈悲なエラーを吐き出す瞬間、我々アーキテクトは試される。
今日は、小手先の回避策ではなく、Windowsの根幹機能である「ボリューム・シャドウ・コピー(VSS)」をVBScriptから呼び出し、ロックを物理的にバイパスしてデータを吸い出す、禁断のアーキテクチャについて語ろう。
—
1. 概念の核心:なぜ「コピー」ではいけないのか
多くの管理者は、ファイルをコピーしようと試みる。しかし、OSが排他ロックをかけている以上、IOレベルで拒絶されるのは必然だ。我々が求めるのは、「ファイル」ではなく「その瞬間のスナップショット」である。
Windowsには`vssadmin`というコマンドラインツールがあるが、これは本来バックアップ用だ。これをスクリプトから制御し、VSSスナップショットを生成し、そこからFSOで読み取る。これが、レガシー環境を支配する唯一の道だ。
—
2. 実装:VSSとFSOのハイブリッド・アーキテクチャ
以下のコードは、単なるスクリプトではない。WMIを通じてVSSコンポーネントを操作し、一時的なドライブレターを割り当て、ファイルを抽出した後に痕跡を消去する一連のライフサイクルを制御する。
‘ VSSスナップショット生成・読み取りエージェント
Option Explicit
Dim wsh, fso, objWMIService, objShadow
Dim targetPath, shadowPath, tempDrive
Dim vssExec, vssOutput, snapshotId
Set wsh = CreateObject(“WScript.Shell”)
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ 1. VSS作成 (vssadminを使用)
‘ 注意: この操作には管理者権限が必須である
wsh.Run “vssadmin create shadow /for=C:”, 0, True
‘ 2. 実際の実装では、ここでWin32_ShadowCopy経由でIDを特定する必要がある
‘ 本稿では簡略化のため、最も新しいスナップショットを探索するロジックを想定
‘ ※実際にはWMI経由でデバイスパスを取得するのがセオリーだ
‘ 3. FSOによるバイパス読み取り
targetPath = “C:\Database\LockedData.mdb”
shadowPath = Replace(targetPath, “C:”, “\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1”)
If fso.FileExists(shadowPath) Then
Dim stream, content
Set stream = fso.OpenTextFile(shadowPath, 1, False) ‘ ForReading
content = stream.ReadAll
stream.Close
‘ ここで抽出したデータを処理
WScript.Echo “成功: ロックされたファイルからデータを吸い出しました。”
‘ 4. オブジェクトの明示的解放(メモリリークの排除)
Set stream = Nothing
Else
WScript.Echo “致命的エラー: スナップショットへのアクセスに失敗しました。”
End If
‘ 5. クリーンアップ (重要)
‘ 放置されたシャドウコピーはシステムのI/O負荷を増大させる
wsh.Run “vssadmin delete shadows /for=C: /all /quiet”, 0, True
Set fso = Nothing
Set wsh = Nothing
—
3. シニアエンジニアが意識すべき「隠れたコスト」
この手法を用いる際、単にコードを動かすだけでは二流だ。以下の3点に注意を払わなければ、システムは自壊する。
- シャドウコピーの保持期限: シャドウコピーはストレージの差分領域(Diff Area)を消費する。大規模な環境で安易に生成・削除を繰り返すと、ディスク書き込み負荷が急増し、OSのレスポンスが極端に悪化する。
- WMIの非同期性: `vssadmin`の完了を待機させることは重要だが、WMI経由でシャドウコピーを操作する場合、オブジェクトのインスタンス化が完了する前に読み取りを試みるレースコンディションが発生しやすい。`Sleep`関数で数秒のバッファを設けるのは、恥ではなく「防御的プログラミング」である。
- メモリの管理: FSOの`ReadAll`は、対象ファイルが巨大な場合、メモリを食いつぶす。ログ解析等で使う場合は、`ReadLine`によるストリーム処理への書き換えを推奨する。
—
4. 結び:レガシーを制御下に置く知見
VBScriptは「古い」のではない。Windowsの深い階層へアクセスできる「極めて軽量なインターフェース」なのだ。APIの仕様、権限の階層、そして排他制御のロジックさえ理解していれば、最新のフレームワークを導入せずとも、既存のシステム上で神のごとき自動化が可能だ。
排他ロックに怯える時代は終わった。今や、我々がシステムを制御する番だ。この知見を、貴殿の堅牢なシステム運用の一助として役立ててほしい。
健闘を祈る。
