VBScriptの暗黒面を制御せよ:WScript.Shell.Execによるノンブロッキング監視の極意
業務自動化の現場において、VBScriptは「枯れた技術」と侮られることがある。しかし、Windowsの心臓部に直結したこの言語を、単なる「バッチファイルの延長」として扱うのはあまりに勿体ない。
多くのエンジニアが陥る罠がある。`WScript.Shell.Run` を使い、`True` を引数に渡して処理の完了を待機する。これでは、外部タスクが終了するまでプロセス全体がフリーズする。「メインスレッドを殺さずにバックグラウンドで重い処理を回し、かつ結果を適切にハンドリングする」――これこそが、堅牢な業務自動化ツールを作るための分水嶺だ。
今日は、`WScript.Shell.Exec` を用いた「ノンブロッキング非同期監視」の技術を授ける。
—
なぜ Run ではなく Exec なのか
`Run` メソッドは同期実行を前提としており、制御が貧弱だ。一方、`Exec` メソッドは `WshScriptExec` オブジェクトを返し、プロセスの状態をリアルタイムに監視できる。
我々が目指すべきは、「メイン処理をブロックしない、かつタイムアウト監視を備えたポーリング処理」である。これを実装しないツールは、無限ループでシステムをハングアップさせる「時限爆弾」と化す。
—
実装の勘所:プロダクション・コード
以下のコードは、単に実行するだけでなく、監視ルーチンを疎結合に設計したテンプレートだ。これをモジュール化して活用せよ。
‘ — ノンブロッキング実行・監視テンプレート —
Option Explicit
Dim shell, oExec, timeoutLimit, startTime
Set shell = CreateObject(“WScript.Shell”)
‘ 1. 非同期実行 (Exec はコマンドプロンプトや実行ファイルを非同期で起動する)
Set oExec = shell.Exec(“powershell.exe -Command “”Start-Sleep -Seconds 5; Write-Output ‘Done'”””)
‘ タイムアウト設定 (秒)
timeoutLimit = 10
startTime = Timer
WScript.Echo “バックグラウンドタスク開始…”
‘ 2. ノンブロッキング・ポーリングループ
Do While oExec.Status = 0 ‘ 0 は WshRunning を意味する
‘ メインスレッドの生存確認(ここでのWScript.Sleepは100-500msが妥当)
WScript.Sleep 200
‘ タイムアウトチェック(保守性の高い設計の要)
If (Timer – startTime) > timeoutLimit Then
oExec.Terminate
WScript.Echo “エラー:処理がタイムアウトしました。”
WScript.Quit 1
End If
‘ 必要であればここでGUIの更新や進捗ログ出力を行う
‘ WScript.Echo “処理中…”
Loop
‘ 3. 終了処理
If oExec.ExitCode = 0 Then
WScript.Echo “タスク完了。出力内容: ” & oExec.StdOut.ReadAll
Else
WScript.Echo “タスク失敗。終了コード: ” & oExec.ExitCode
End If
—
堅牢な設計のための3つの鉄則
1. タイムアウトは「必須」の安全装置
非同期処理において、外部コマンドが何らかの理由(ファイルロックや予期せぬダイアログ出現)でハングアップした場合、このスクリプトだけが生き残り、メモリを食いつぶす。`Timer` 関数を用いた経過時間チェックは、どんなに小規模な自動化であっても必ず組み込むこと。
2. 標準ストリームのバッファ溢れに注意
`oExec.StdOut.ReadAll` を使う際、出力が膨大だとバッファがいっぱいになり、プロセスがデッドロックすることがある。ログの出力が膨大になることが予測される場合は、一時ファイル経由でリダイレクトし、終了後に読み込む設計に変えるべきだ。
3. ファイル・DB連携時の排他制御
非同期処理がファイルを書き換える場合、メインスクリプトとの競合が発生する。
- ファイル: 書き込み完了を判定するために、`FileSystemObject` での更新日時監視か、実行終了の `ExitCode` 確認を厳格に行うこと。
- DB: データベースへ直接書き込む際は、必ずトランザクション分離レベルを意識するか、SQLの実行完了を待機する設計にすること。
—
最後に:エンジニアとしての矜持
VBScriptは古いが、そのシンプルさは時に強力な武器になる。だが、そのシンプルさゆえに「適当な書き方」がまかり通ってしまう。
今回伝授したポーリングパターンは、単なるコードの断片ではない。「システム全体の安定性を、スクリプト側で担保する」というアーキテクトの思想そのものだ。
君たちがこれから作る自動化ツールが、現場を楽にするだけでなく、誰かが夜中に呼び出されるようなトラブルを起こさない「沈黙の功労者」となることを期待している。
さあ、コードを書け。ただし、細部まで魂を込めて。
