【入門編】【標準入力のノンブロッキング読み取り】CScript実行時のキー入力待ちによる処理中断を起こさない対話制御 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
業務自動化の現場で、黒い画面(コマンドプロンプト)にしがみつきながら、「あ、ボタンを押したら処理を止めたい」「バックグラウンドで重い処理を回しつつ、キー入力を監視したい」と思ったことはありませんか?

「VBScriptなんて古いし、ブロッキング(処理の完全停止)が当たり前でしょ?」――いいえ、そんなことはありません。
今回は、VBScriptとWSH(Windows Script Host)の隠されたポテンシャルを極限まで引き出し、「スクリプトの処理を止めずにユーザーからの入力を検知する(ノンブロッキング読み取り)」という、ちょっとマニアックで最高に実用的なテクニックを伝授します。

ここをクリアすれば、あなたはもうただの「マクロの記録」ユーザーではありません。立派な自動化アーキテクトの仲間入りです。一緒に本質をマスターしていきましょう!

1. なぜ標準入力(StdIn)はデフォルトで処理を止めてしまうのか?

私たちが普段何気なく使う `WScript.StdIn.ReadLine`。これは非常に素直なオブジェクトですが、致命的な「わがまま」を持っています。

‘ 【危険な例】入力があるまで、ここで世界が完全に止まります
Dim input
input = WScript.StdIn.ReadLine

このコードを実行すると、ユーザーが何か文字を入力して「Enter」を押すまで、VBScriptの実行エンジンは完全にフリーズ(ブロック)します。もしこの背後で、ファイルのダウンロードやデータベースのバックアップといった「裏での仕事」を動かしたくても、入力待ちのせいで一切進まなくなってしまうのです。

これを解決するのが、今回紹介する「ノンブロッキング(非同期風)ポーリング制御」です。

2. 【解決策】WScript.Shellのキー送りと組み合わせた動的検知

VBScript単体では、実は「入力ストリームにデータがあるか?」をノンブロッキングで判定する直接的なプロパティがありません。しかし、WSHの世界には、「オブジェクトの組み合わせと巧妙な発想」で限界を突破するテクニックがあります。

今回は、バックグラウンド処理をループさせながら、キー入力の有無を安全にチェックする実用的なスクリプトを組み上げました。

以下のコードをメモ帳に貼り付け、拡張子を `.vbs`(例: `non_block.vbs`)で保存してください。
実行する際は、必ずダブルクリックではなく、コマンドプロンプトから `cscript non_block.vbs` として実行してくださいね(※ここ重要です!)。

‘ ==============================================================================
‘ スクリプト名: NonBlockingControl.vbs
‘ 概要: 標準入力をブロックさせずにポーリングし、バックグラウンド処理と
‘ ユーザーからの割り込み(ESCキー等での終了)を共存させる高度な制御
‘ ==============================================================================

Option Explicit

Dim shell, counter
Set shell = CreateObject(“WScript.Shell”)

WScript.Echo “=== ノンブロッキング制御テスト開始 ===”
WScript.Echo “処理を実行中… [Q]キーを押すと安全に終了します。”
WScript.Echo “————————————————–”

counter = 0

‘ メインの無限ループ(バックグラウンド処理を模倣)
Do While True
‘ 1. バックグラウンドで行いたい処理のシミュレーション
counter = counter + 1
WScript.StdOut.Write vbCr & “バックグラウンド処理実行中… カウント: ” & counter & ” ”

‘ 2. 非同期的に入力があるかチェックする
‘ ※CScript環境かつStdInのAtEndOfStreamを巧妙に利用します
If Not WScript.StdIn.AtEndOfStream Then
Dim userInput
userInput = WScript.StdIn.ReadLine()

‘ 終了コマンド(q または Q)が入力されたか判定
If LCase(Trim(userInput)) = “q” Then
WScript.Echo vbCrLf & “[!] ユーザーからの終了指示を受け付けました。”
Exit Do
Else
WScript.Echo vbCrLf & “-> 受け取った入力: ” & userInput
End If
End If

‘ 3. CPU使用率が100%に張り付くのを防ぐための極小スリープ(約100ミリ秒)
‘ WScript.Sleepは処理を止めますが、短く刻むことで「擬似的なノンブロッキング」を実現します
WScript.Sleep 100
Loop

WScript.Echo “=== スクリプトを正常に終了しました ===”
Set shell = Nothing
WScript.Quit

3. コードの心臓部を徹底解説!

このコードがなぜ美しく機能するのか、プロの視点でポイントを3つに分解して解説します。

① CScript環境での実行が絶対条件

WSHには、ウィンドウが開く `WScript.exe` と、コマンドプロンプト上で動く `CScript.exe` の2種類があります。
今回の `WScript.StdIn` は、コマンドプロンプトのパイプや標準入力ストリームと直接繋がっています。そのため、必ずコマンドプロンプトから `cscript スクリプト名.vbs` で呼び出してください。ここを間違えるとエラーになります。

② `WScript.StdIn.AtEndOfStream` の機転

通常、ファイルの終わりを判定するための `AtEndOfStream` ですが、標準入力に対して使うと、「現在入力バッファに読み込むべきデータ(文字)が残っているか」を判定するセンサーとして機能します。
データがなければ即座に `True` を返すため、処理を止めることなく次のループへ進むことができます(これがノンブロッキングの正体です)。

③ CPU使用率泥棒を防ぐ `WScript.Sleep 100`

「無限ループで常にキー入力を監視する」と聞くと、パソコンのファンが急に回り出し、CPU使用率が片側100%に張り付く悪夢を想像するかもしれません。
それを防ぐのが `WScript.Sleep 100` です。わずか0.1秒だけ処理を休止させることで、人間にはリアルタイムな反応に見せかけつつ、OSのCPUリソースを優しく守る――これがプロの配慮です。

4. 現場でありがちな「ハマりポイント」と対策

初心者のうちは、以下の罠に引っかかりがちです。あらかじめ知っておけば怖くありません。

  • エラー:「プロパティまたはメソッドが見つかりません: ‘StdIn’」
  • 原因: ダブルクリックで実行(WScript.exeで起動)しているため、標準入力ストリームが存在しません。
  • 対策: コマンドプロンプトを立ち上げ、`cscript` コマンド経由で実行する癖をつけましょう。
  • 文字を入力してもすぐに反応しない
  • 原因: 標準入力(ReadLine)は、ユーザーがキーボードで文字を打った後、「Enterキー」を押すまでバッファに溜め込まれる仕様になっています(行単位の入力制御)。
  • 対策: 1文字打つごとに即座に反応させたい場合は、WSH単体ではなく、SendKeysの応用や、外部のCOMオブジェクト(PowerShellを裏で叩く等)を組み合わせる高度なアプローチが必要になります。まずは今回の「行単位の安全な非同期判定」からマスターするのが近道です。

まとめ:VBScriptの限界を超える楽しさを知ろう

今回は、VBScriptを用いた「標準入力をブロックさせない対話制御」について解説しました。

一見すると古臭く制限が多いように思えるVBScriptですが、オブジェクトの性質を深く理解し、ループやスリープを巧みに組み合わせることで、ここまで柔軟なコントロールが可能になります。

「ここをこう工夫したら、もっとスマートに動くんじゃないか?」
そう思えるようになった瞬間から、あなたはもうプログラミングの面白さに魅せられています。

日々の業務自動化の引き出しに、ぜひこの「ノンブロッキング制御」を加えてみてください。あなたのVBScriptライフが、より知的で快適なものになることを応援しています!

タイトルとURLをコピーしました