VBScriptで実現する「ノンブロッキングCLI」:バックグラウンド処理と入力監視の極意
業務自動化の現場において、VBScript(WSH)は「枯れた技術」と揶揄されることがある。だが、真のエンジニアは知っている。OSの深層に最も近く、極めて軽量に動作するこの言語こそ、真の「グルーコード(接着剤)」であることを。
多くの開発者が躓くのが、「処理を実行しながら、ユーザーの入力(割り込み)を拾う」という命題だ。通常、`WScript.StdIn.ReadLine` を実行すればスクリプトは止まる。しかし、我々は止まってはならない。
今日は、CScript環境下で、バックグラウンドの重いタスクを回しながら、ユーザーのキー入力をリアルタイムに監視する「ノンブロッキングI/O」の設計手法を伝授する。
—
なぜ従来の「同期処理」ではダメなのか?
一般的なツール作成者は、入力を待つ際に `ReadLine` を使う。これは「ブロッキング処理」であり、入力があるまでスクリプトの実行スレッドが完全に停止する。
もしあなたが、ログの監視やAPIへの定期ポーリングをしながら、特定のキー入力(例えば「Q」で停止など)を待つツールを作りたい場合、同期処理ではそれが物理的に不可能だ。この壁を突破するには、「ポーリング監視」という戦略が必要になる。
—
設計思想:Non-Blocking I/O パターン
今回の肝は `WScript.StdIn.AtEndOfLine` を活用することだ。
これは「現在、入力ストリームに未読のデータがあるか」を判定するプロパティである。これと `WScript.Sleep` を組み合わせることで、「CPU負荷を抑えつつ、入力を監視し続ける」という理想的なループ構造を作る。
実装コード:堅牢なノンブロッキング・シェル
このコードは、メインループでバックグラウンド処理を回しつつ、ユーザー入力を非同期にチェックするテンプレートだ。プロダクション環境での安定性を考慮し、エラーハンドリングを最小限に組み込んでいる。
‘ CScript.exe で実行すること (wscript.exeではStdInが使えないため)
Option Explicit
Dim bRunning : bRunning = True
Dim iCounter : iCounter = 0
WScript.StdOut.WriteLine “— 監視システム開始 [Q]キーで終了 —”
Do While bRunning
‘ 1. 入力ストリームの監視
‘ AtEndOfLineは入力がバッファにあるかを確認する
If Not WScript.StdIn.AtEndOfStream Then
‘ ReadLineで1行分読み取る
Dim sInput : sInput = LCase(WScript.StdIn.ReadLine)
If sInput = “q” Then
WScript.StdOut.WriteLine “終了シグナルを受信しました。”
bRunning = False
Else
WScript.StdOut.WriteLine “コマンド ‘” & sInput & “‘ を受信”
End If
End If
‘ 2. メインのバックグラウンド処理
‘ ここでDB接続やファイル監視などの重い処理を回す
iCounter = iCounter + 1
If iCounter Mod 100 = 0 Then
WScript.StdOut.WriteLine “バックグラウンド処理中… (ループ回数: ” & iCounter & “)”
End If
‘ 3. CPU負荷を抑えるためのSleep (超重要)
‘ 0にするとCPUを100%消費するため、最低100ms程度は空けるのが定石
WScript.Sleep 100
Loop
WScript.StdOut.WriteLine “システムを停止しました。”
—
現場で生き残るための「4つの鉄則」
コードをコピペするだけでは、現場の荒波は越えられない。この実装をプロダクションレベルにするための知見を共有する。
1. CScript.exe を強制する
WScript.exe(GUI版)で実行すると `StdIn` が存在せずエラーになる。バッチファイル内で以下のように記述し、強制的にCScriptへ切り替えるのが「プロの作法」だ。
@echo off
cscript //nologo “%~dp0your_script.vbs”
2. Sleep の重みを知る
`WScript.Sleep` の値は、ツールの「応答性」と「負荷」のトレードオフだ。
- `Sleep 10`: 応答性は最高だが、CPU負荷が高まる。
- `Sleep 1000`: 負荷は低いが、入力に対するレスポンスが鈍い。
現場では、バックグラウンド処理の重さに合わせ、100ms〜500msの間で調整するのが最もバランスが良い。
3. ファイル・DB連携時の注意点
このループ内でファイルI/OやDB接続を行う場合、「ループのたびに接続/切断」を繰り返すのは愚策だ。接続オブジェクト(ADODB.Connection等)はループの外でインスタンス化し、ループ内ではデータの読み書きのみを行うこと。さもなくば、接続リソースの枯渇(コネクションリーク)でツールは数時間で死ぬ。
4. 異常終了対策
バックグラウンド処理が複雑になる場合、`On Error Resume Next` で囲むのは最低限だが、さらに `Err.Number` をログ出力する仕組みを導入せよ。スクリプトが黙って消えるのが、運用において最も恐ろしい事態である。
—
最後に:なぜ今、VBScriptなのか
モダンな言語(PythonやGo)がある中で、なぜ我々がVBScriptを語るのか。それは、「クライアントPCの環境を一切汚さず、メモ帳一つで即座に運用を開始できる」という圧倒的なスピード感こそが、業務改善の現場で最も求められる価値だからだ。
この「ノンブロッキング・シェル」のテンプレートを武器に、あなたの手元にある退屈なルーチンワークを、洗練された自動化プロセスへと昇華させてほしい。
健闘を祈る。
