VBScriptで構築する「枯れた」ホットフォルダ監視の極意:無限ループを制する者はシステムを制す
かつて、サーバーサイドの自動化といえばVBScriptだった。現代ではPowerShellやPythonにその座を譲ったように見えるが、レガシーなWindows環境、あるいは軽量なエージェントが求められる現場において、FSO(FileSystemObject)を駆使したポーリング監視は、今なお「最も信頼性の高い」選択肢の一つだ。
だが、安易な `WScript.Sleep` はシステムの死を招く。今日は、伝説的なアーキテクトの視点から、メモリリークを許さず、CPU負荷を最小化し、数年単位の稼働に耐えうる監視エンジンの実装論を説く。
—
1. なぜ「Count」プロパティを信じてはいけないのか
初心者は `Folder.Files.Count` を監視のトリガーにする。だが、これは罠だ。ファイルサイズが大きい場合や、ネットワーク越しにコピーが行われている最中、OSはファイルハンドルを掴んだままであり、VBScriptが「ファイルが存在する」と認識した瞬間に処理を開始しても、ファイルはまだロックされている。
真のエンジニアは、ファイルの存在確認ではなく「排他ロックの回避」を設計する。
2. 極限まで最適化した監視ループの実装
以下のコードは、単なる監視スクリプトではない。オブジェクトのライフサイクルを管理し、メモリの断片化を抑制する構造だ。
Option Explicit
‘ — 定数設定 —
Const WATCH_FOLDER = “C:\InputFolder”
Const SLEEP_TIME = 2000 ‘ 2秒間隔
Dim fso, folder, file
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ メインループ:無限の安定性を求めて
Do
If fso.FolderExists(WATCH_FOLDER) Then
Set folder = fso.GetFolder(WATCH_FOLDER)
‘ ファイルが存在する場合のみ処理
If folder.Files.Count > 0 Then
For Each file In folder.Files
‘ 処理可能か判定(排他ロック確認の模倣)
If IsFileAccessible(file.Path) Then
Call ProcessFile(file)
End If
Next
End If
‘ オブジェクトの明示的解放によるメモリ管理
‘ これを怠ると、長期間稼働でWScriptプロセスが肥大化する
Set folder = Nothing
End If
WScript.Sleep SLEEP_TIME
Loop
‘ — ファイル排他チェック関数 —
Function IsFileAccessible(filePath)
On Error Resume Next
Dim f
Set f = fso.OpenTextFile(filePath, 8, False) ‘ 追記モードで開けるか試行
If Err.Number = 0 Then
f.Close
IsFileAccessible = True
Else
IsFileAccessible = False
End If
On Error GoTo 0
End Function
‘ — 実際の業務処理 —
Sub ProcessFile(file)
WScript.Echo “処理開始: ” & file.Name
‘ ここに複雑な自動処理を記述する
‘ file.Move “C:\Processed\” & file.Name
End Sub
—
3. チーフアーキテクトからの「極限の知見」
A. メモリリークを防ぐ唯一の真実
VBScriptのガベージコレクションは頼りにならない。ループ内でのオブジェクト生成(特に `Set` を伴うもの)は、必ずループの終了時、あるいは `Set obj = Nothing` を用いて、明示的に参照カウンタをゼロにしなければならない。特に `Scripting.FileSystemObject` は強力だが、生成・破棄のコストが高いため、メインループの外で生成し、使い回すのが鉄則だ。
B. 排他制御のテクニック
上記の `IsFileAccessible` 関数は、ファイルが書き込み中(ロック中)かどうかを、実際に「追記モードで開けるか」という力技で判定している。OSのAPIを直接叩くラッパーを書くのが理想だが、VBScript単体で完結させるなら、これが最も現実的かつ強力な防衛策である。
C. レガシー環境での保守性
もしこのスクリプトをタスクスケジューラで運用するなら、必ず「最上位特権で実行」し、「停止ボタン」の挙動を考慮せよ。さらに、万が一の異常終了(スタックオーバーフローや予期せぬエラー)に備え、別の「監視用監視プロセス」を別スクリプトで起動させておくのが、ミッションクリティカルな環境におけるプロの流儀だ。
—
結論:技術は目的ではない、手段だ
最新のクラウドネイティブな構成がもてはやされる今、なぜVBScriptなのか。それは、「依存関係がゼロ」だからだ。ランタイムをインストールする必要はなく、OS標準のエンジンだけで動く。この「環境を選ばない」という強みは、どれほど技術が進化しても決して失われない。
コードは美しく、そしてタフでなければならない。君が書くスクリプトが、明日の朝、何事もなかったかのように動いていること。それこそが、エンジニアとしての最大の誇りであるはずだ。
