【テクニカル・上級編】【排他制御・エラー回避】ファイルロック時に落ちないFSO操作とリトライループの実装パターン – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptの「泥沼」から脱却せよ:FSOにおける排他制御と生存戦略

VBScriptを「過去の遺物」と切り捨てるのは簡単だ。だが、Windowsの心臓部、すなわちレガシーなバッチ処理やオンプレミスの保守現場において、この言語は依然として不可欠なインフラである。

特に、`Scripting.FileSystemObject`(以下FSO)を用いたファイル操作において、他プロセスによるファイルロック――いわゆる「Permission Denied (800A0046)」との戦いは、エンジニアが避けて通れない登竜門だ。今日は、この泥臭い現場で生き残るための「極限の排他制御パターン」を伝授する。

—

1. なぜFSOは「待ってくれない」のか

FSOはシンプルだが、本質的に「楽観的」な設計だ。ファイルが開かれているかを確認するメソッドは存在せず、アクセスを試みて初めてエラーを吐く。

ここで多くの初学者が陥る罠が、安易な `On Error Resume Next` と、無策な再試行だ。CPUリソースを食いつぶすだけの空ループや、メモリリークを誘発する不適切なオブジェクト管理は、数ヶ月後のシステム停止を約束するようなものだ。

2. 堅牢なリトライ・パターン:指数バックオフの実装

単なる固定秒数の待機は、競合が激しい環境では無意味だ。以下のコードは、バックオフ戦略を取り入れ、かつオブジェクトのライフサイクルを厳密に管理するプロ仕様の実装である。

‘ — 極限の排他制御:ファイル移動処理 —
Option Explicit

Dim fso, strSource, strDest
Set fso = CreateObject(“Scripting.FileSystemObject”)

strSource = “C:\Data\Input.csv”
strDest = “C:\Data\Archive\Input.csv”

If MoveFileWithRetry(fso, strSource, strDest, 5, 1000) Then
WScript.Echo “処理成功”
Else
WScript.Echo “致命的エラー:排他ロックを解除できませんでした。”
WScript.Quit 1
End If

‘ 明示的なオブジェクト解放
Set fso = Nothing

‘ — 実装ロジック —
Function MoveFileWithRetry(objFSO, strSrc, strDst, intMaxRetries, intWaitMs)
Dim i, blnSuccess
blnSuccess = False

For i = 1 To intMaxRetries
On Error Resume Next
objFSO.MoveFile strSrc, strDst

If Err.Number = 0 Then
blnSuccess = True
On Error Goto 0
Exit For
End If

‘ ロックされている場合(800A0046等)はリトライ
WScript.Sleep intWaitMs i ‘ 指数的に待機時間を増やす
Err.Clear
On Error Goto 0
Next

MoveFileWithRetry = blnSuccess
End Function

3. チーフアーキテクトの視点:アーキテクチャの真髄

上記のコードを単にコピーするだけでは不十分だ。現場で「落ちない」システムを構築するために、以下の3点を脳に刻み込んでほしい。

A. オブジェクトのライフサイクル管理

VBScriptのガベージコレクションを信じてはいけない。`Set obj = Nothing` を怠ることは、小規模なスクリプトでは許されても、常駐型のバッチや長時間稼働する環境では「メモリの腐敗」を招く。特にループ内でオブジェクトを生成・破棄する場合は、スコープを最小化せよ。

B. APIレベルの「真の排他確認」の回避

どうしてもFSOで判定できない場合、Windows APIの `CreateFile` を呼ぶという手があるが、VBScript単体ではハードルが高い。もしAPIが必要なほどの高頻度アクセス環境であれば、それは設計上の敗北だ。VBScriptの役割は「簡素な自動化」にある。複雑な排他制御が必要なら、PowerShellへ移植する勇気を持つべきだ。

C. エラーハンドリングの「哲学」

`On Error Resume Next` は、「狙った例外以外は握りつぶさない」のが鉄則だ。今回のようなファイルロック(0x800A0046)以外のエラー(ディスクフル、権限不足、パス不正)までリトライで隠蔽してはならない。本番環境でデバッグ不可能な闇を作ることになる。

—

最後に:技術への敬意

VBScriptで書かれたコードが、10年後も誰かの業務を支えている。それがこの言語の恐ろしさであり、美しさだ。

「とりあえず動く」コードから、「枯れた堅牢性を持つ」コードへ。あなたが今日書くその数行が、未来の運用者の夜を安らかにする。それが、エンジニアとしての矜持であるはずだ。

妥協なき実装を続けよ。コードは嘘をつかない。