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

スポンサーリンク

VBScriptを掌握せよ:ファイルロックに屈しない「堅牢なFSO操作」の極意

業務自動化の現場において、`Scripting.FileSystemObject`(以下FSO)は最も身近な武器だ。しかし、その簡便さゆえに「とりあえず動くコード」を書いて満足していないだろうか?

特にExcelや外部バッチと共有するファイルを扱う際、「Permission Denied(書き込み権限がありません)」という悪魔のエラーに直面し、自動化ツールが呆気なく停止する――これは初学者が必ず通る壁であり、プロとの境界線でもある。

今日は、ファイルロックという避けられない障害を前提とした「止まらないコード」の書き方を伝授する。

—

1. なぜ「単純なFSO操作」は死ぬのか

VBScriptで最もやってはいけないのが、以下のコードだ。

‘ 危険な実装例:エラーハンドリングなし
Set fso = CreateObject(“Scripting.FileSystemObject”)
fso.CopyFile “C:\data.xlsx”, “C:\backup\data.xlsx”

このコードが失敗するのは、OSのせいではない。「排他制御」という概念を無視している設計のせいだ。 ファイルが他プロセスで開かれているとき、Windowsは対象ファイルへのアクセスを拒絶する。ここでコードが停止すれば、業務フロー全体が止まる。

プロのエンジニアは、「エラーは起きるもの」という前提で設計する。

—

2. 堅牢なリトライ戦略:指数バックオフの思想

単に`Sleep`を入れるだけでは不十分だ。ロックが解除されるまでリトライしつつ、システム負荷を考慮した「待機戦略」を組み込む必要がある。

以下のコードは、プロダクション環境でそのまま使える「リトライロジック付きファイルコピー関数」だ。

プロダクション・コード:`SafeFileCopy`

‘ 引数:コピー元、コピー先、最大リトライ回数、リトライ間隔(ms)
Function SafeFileCopy(sourcePath, destPath, maxRetries, sleepMs)
Dim fso, i, success
Set fso = CreateObject(“Scripting.FileSystemObject”)
success = False

For i = 1 To maxRetries
On Error Resume Next ‘ エラーをトラップする
fso.CopyFile sourcePath, destPath, True

If Err.Number = 0 Then
success = True
On Error GoTo 0
Exit For
Else
‘ ログ出力(必要に応じて)
‘ WScript.Echo “Retry ” & i & “: ” & Err.Description
Err.Clear
WScript.Sleep sleepMs ‘ 指定時間待機して再試行
End If
On Error GoTo 0
Next

SafeFileCopy = success
End Function

‘ — 実行例 —
If SafeFileCopy(“C:\target.xlsx”, “C:\backup\target.xlsx”, 5, 2000) Then
WScript.Echo “成功しました。”
Else
WScript.Echo “致命的エラー:ロックが解除されませんでした。”
End If

—

3. 実務で差がつく「3つの設計指針」

上記のコードを実装する際、以下の視点を持つことで、保守性が劇的に向上する。

① タイムアウト時間を「業務」に合わせる

Excelファイルをマクロで保存する処理を待つ場合、リトライ間隔は長めに取るべきだ。`2000ms`(2秒)× `5回` = `10秒`程度の猶予があれば、大抵のバッチ処理の衝突は回避できる。

② `On Error Resume Next` のスコープを最小化する

この命令は「エラーを無視する」ものではなく、「エラーを制御下に置く」ためのものだ。広範囲に書くと、ファイルロック以外の予期せぬバグ(パス間違いなど)を見逃す原因になる。必ず操作の直前で有効にし、直後で`On Error GoTo 0`に戻すこと。

③ ロックを「検知」するのではなく「試行」する

「ファイルが開かれているか」を事前に判定しようとすると、判定した瞬間と操作する瞬間の間にロックが発生する「競合状態(Race Condition)」が起きる。「操作を試みて、失敗したら待つ」というリアクティブな設計こそが、最も堅牢な解だ。

—

最後に:自動化のプライド

自動化エンジニアにとって、コードは「書いたら終わり」ではない。深夜や早朝、誰も見ていないところで確実に動き続け、失敗したときには自分にログを残してくれる。それがプロの仕事だ。

「エラーが起きたから止まりました」と報告するのではなく、「ロックが発生しましたが、自動的にリトライして完遂しました」と報告する。 この差が、あなたのエンジニアとしての価値を決める。

さあ、その貧弱なコードを書き換え、止まらない自動化システムを構築してほしい。質問があればいつでも来い。現場からは以上だ。

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