VBScriptの「書き込み競合」を制する:リトライ機能付きログライター実装ガイド
こんにちは。現場で長年、スクリプトの保守に奔走してきたエンジニアです。
VBScriptでログを記録する際、`Scripting.FileSystemObject`(以下FSO)を安易に使っていませんか?「動いているから大丈夫」と油断していると、ある日突然、複数のプロセスが同時にログを書き込もうとした瞬間に「エラー 70: 書き込みできません(Permission Denied)」という悪夢に直面します。
今日は、そんな競合トラブルをスマートに回避する「リトライ機能付きログライター」の作り方を解説します。これをマスターすれば、あなたのスクリプトは一気に「業務レベルの堅牢さ」を獲得します。
—
1. なぜ「競合」は起きるのか?
Windowsにおいて、FSOの `OpenTextFile` メソッドは、ファイルを開く際に「排他制御」を要求します。他のプロセスがそのファイルを掴んでいると、VBScriptは待機することなく即座にエラーを吐いて終了します。
これを防ぐための鉄則は一つ。「一度ダメでも、少し時間を置いてから再挑戦する」ことです。
—
2. 核心となる実装:指数バックオフ戦略
単に「すぐ再試行」するのではなく、「少しずつ待ち時間を延ばす」のがプロの技術です。これを「指数バックオフ」と呼びます。
実装コード
このコードをあなたのスクリプトの共通ライブラリとして保存しておけば、どんなツールでも安全にログを残せます。
‘ — ログ書き込み関数(リトライ機能付き) —
Sub WriteLog(strFilePath, strMessage)
Dim fso, ts, i, retryCount, waitTime
Set fso = CreateObject(“Scripting.FileSystemObject”)
retryCount = 5 ‘ 最大リトライ回数
waitTime = 100 ‘ 初回の待機ミリ秒数
For i = 1 To retryCount
On Error Resume Next ‘ エラーを無視して自前で判定する
‘ 8:追記モード(ForAppending), True:ファイルがなければ作成
Set ts = fso.OpenTextFile(strFilePath, 8, True)
If Err.Number = 0 Then
ts.WriteLine Now & ” : ” & strMessage
ts.Close
On Error GoTo 0
Exit Sub ‘ 成功したら抜ける
End If
‘ エラー発生時は少し待機(指数バックオフ)
WScript.Sleep waitTime
waitTime = waitTime 2 ‘ 次の待機時間を倍にする
Err.Clear
On Error GoTo 0
Next
‘ 最後までダメだった場合
WScript.Echo “ログ書き込みに失敗しました: ” & strFilePath
End Sub
‘ — 使用例 —
WriteLog “C:\Logs\AppLog.txt”, “プロセスを開始しました。”
—
3. コードのポイントを解説
① `On Error Resume Next` の正しい使い方
VBScriptの鉄則です。エラーが起きた瞬間に止まるのではなく、エラー情報をあえて放置し、`If Err.Number = 0` で「成功したか?」を確認する。これが堅牢なロジックの入り口です。
② `WScript.Sleep` でプロセスを優しく待機
VBScriptは非常に軽量ですが、それゆえに高速に動きすぎてファイルロックの隙間を縫うことができません。`Sleep` を挟むことで、他のプロセスがファイルを解放する「猶予」を与えてあげてください。
③ なぜ「指数バックオフ」なのか?
もし10個のプロセスが同時に動いている場合、全員が「10ミリ秒後に再試行」すると、また全員同時にぶつかります。待ち時間を倍々に増やすことで、プロセス同士のタイミングをズラし、衝突の連鎖を自然に解消させます。
—
4. 初学者が陥りやすい罠
- ファイルパスの指定: FSOは相対パスに弱い傾向があります。可能な限り `WScript.ScriptFullName` から親フォルダを特定し、フルパスで指定するようにしましょう。
- オブジェクトの解放忘れ: `Set ts = Nothing` は必ず行いましょう。メモリリークを防ぐことは、安定稼働の第一歩です。
—
最後に:VBScriptの先へ
VBScriptは古い言語だと言われますが、Windows環境において「OSそのものに標準搭載されている」という圧倒的な利点は今も揺るぎません。追加インストールなしで、ここまで強力な制御ができるのです。
「書き込みエラー」に遭遇したら、それはあなたのコードが「成長した証」です。ぜひ、このリトライロジックをあなたの武器に加え、どんな現場でも動じない安定した自動化ツールを作り上げてください。
ここをクリアしたあなたなら、次は `ADODB.Stream` を使った文字コード変換や、`WMI` を使ったシステム監視といった、より深い世界も必ず掌握できます。応援しています!
