VBScriptを掌握する極限の知見:WScript.Sleepによる同期制御とプロセスの「真の」待機
レガシーシステムの深淵に潜る諸君、ようこそ。
VBScriptという言語は、現代のメモリ管理やガベージコレクションの概念から見れば、極めてプリミティブな存在だ。しかし、この「泥臭い」ツールを完璧に制御できる者こそが、Windowsという巨大なOSの深部で、真の自動化を実現できる。
今回は、外部プロセスとの連携における「最も基本的であり、かつ最も軽視されがちな」同期制御について、アーキテクトの視点から解剖する。
—
1. なぜ「Sleep」を語るのか:CPUサイクルを無駄にするな
`WScript.Sleep`は、単なる時間稼ぎの道具ではない。これは、「OSのスケジューラに対する謙譲」である。
ループ処理で条件判定を繰り返す際、`Sleep`を挿入しなければ、スクリプトは単一スレッドを占有し、CPUコアを飽和させる。システム管理者が陥る最大の罠は、この「ビジーループ」による負荷増大だ。我々の任務は、システムを停止させることではなく、システムを調律することにある。
—
2. 外部プロセス待機の極意:ポーリング・パターンの最適化
外部アプリケーション(EXE)を起動し、その完了を待機して後続処理を行う場合、`WScript.Shell`の`Run`メソッドに`bWaitOnReturn = True`を指定するのが定石だ。しかし、これでは「プロセスがハングした際、スクリプトも永遠に停止する」という致命的な欠陥がある。
真のエンジニアは、「タイムアウト付きの非同期監視」を実装する。
実践的な待機制御コード
Option Explicit
‘ 定数定義:リトライ間隔と最大試行回数
Const RETRY_INTERVAL = 500 ‘ 0.5秒
Const MAX_RETRIES = 120 ‘ 60秒間待機
Function ExecuteAndMonitor(strCommand)
Dim objShell, objExec, intCount
Set objShell = CreateObject(“WScript.Shell”)
‘ プロセスを非同期で実行
Set objExec = objShell.Exec(strCommand)
intCount = 0
‘ 終了フラグ(Status)を監視しつつ、SleepでCPUを解放する
Do While objExec.Status = 0
If intCount >= MAX_RETRIES Then
objExec.Terminate ‘ タイムアウト時は強制終了
ExecuteAndMonitor = False
Exit Function
End If
WScript.Sleep RETRY_INTERVAL
intCount = intCount + 1
Loop
ExecuteAndMonitor = True
‘ 明示的解放:VBScriptのガベージコレクションを信じるな
Set objExec = Nothing
Set objShell = Nothing
End Function
—
3. メモリとライフサイクルの哲学
VBScriptにおいて、`Set obj = Nothing`を怠ることは、戦場に銃を置いていくのと同義だ。
特に、ループ内でオブジェクトを生成・破棄する場合、メモリリークは累積する。VBScriptのエンジンである`wscript.exe`や`cscript.exe`は、プロセス終了までメモリを保持し続ける傾向がある。特に、WMI経由でプロセスを監視したり、ファイルシステムオブジェクト(FSO)を多用する場合、「オブジェクトの寿命を最短にする」ことが、長時間稼働する監視スクリプトの安定性を左右する。
シニアエンジニアが守るべき鉄則
1. スコープの最小化: ループの直前で生成し、ループの直後で解放する。
2. エラーハンドリング: `On Error Resume Next`を多用する諸君は、必ず`Err.Clear`でエラーバッファをリセットせよ。汚れた状態での判定は、ゴーストバグの温床となる。
3. プロセス名の特定: `Exec`ではなく`WMI(Win32_Process)`を使用する場合、プロセスID(PID)を追跡せよ。プロセス名のみでの監視は、同名の別プロセスを誤認するリスクがある。
—
4. 結び:レガシーを「洗練」へ昇華させる
VBScriptで記述されたシステムが保守困難に陥るのは、言語のせいではない。それを書いた人間が、OSの挙動とプロセスのライフサイクルを理解していないからだ。
`WScript.Sleep`は、単に一時停止する命令ではない。それは、「この処理の間、OSの他のタスクに資源を譲渡する」というエンジニアの意思表示である。
この知見を胸に、諸君の現場にある荒れ果てたバッチスクリプトを、静寂かつ正確に動作する精密機械へと作り変えてほしい。それが、レガシー環境を支配するアーキテクトの責務だ。
—
追伸:もし諸君が、より複雑な非同期通知を必要としているなら、Windows APIの`WaitForSingleObject`を呼び出すべきだ。だが、それはまた別の機会に語ることにしよう。
