【入門編】【コンソール画面制御】CScript実行時の自動終了防止と、画面クリア・標準入力待ちを組み込んだ対話型CLIの作成 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

やぁ、よく来てくれたね。日々の業務効率化や自動化に取り組む中で、「Excelマクロの記録機能」から一歩踏み出し、もっと自由で強力なツールを作りたいと思い始めたところかな?

そんな君に今回伝授するのは、Windowsに標準搭載されているVBScript(Visual Basic Scripting Edition)を使いこなし、まるでプロのインフラエンジニアが使うような「対話型のコマンドラインツール(CLI)」を構築する極意だ。

「VBScriptなんて、ダブルクリックするとメッセージボックスが出るだけの古い技術でしょう?」

もしそう思っているなら、今日その認識は完全に覆る。VBScriptの実行環境であるWSH(Windows Script Host)の内部挙動を理解し、標準入出力(I/O)を正しくハンドリングすれば、驚くほど軽量で、堅牢で、ユーザーフレンドリーなコンソールアプリケーションが作れるんだ。

この記事を読み終える頃には、「一瞬で消えてしまう黒い画面」を完全に手懐け、画面のクリアや入力チェック(バリデーション)を自由自在にコントロールできるようになっているよ。

さあ、VBScriptの深淵にして基本のマスターロードへ、一歩を踏み出そう!

1. なぜ画面が一瞬で消えるのか?「Wscript」と「Cscript」の決定的な違い

VBScriptを学び始めた人が最初につまずくのが、「スクリプトを実行した瞬間に黒い画面(コマンドプロンプト)が一瞬だけ表示されて消えてしまう」という現象だ。

この謎を解く鍵は、Windowsがスクリプトを実行する「エンジン(ホストプロセス)」の違いにある。実はWindowsには、VBScriptを動かすエンジンが2種類用意されているんだ。

| エンジン名 | 正式名称 | 主な用途(キャラクター) |
| :— | :— | :— |
| `WScript.exe` | Windows Script Host (GUI版) | メッセージボックス(`MsgBox`)など、視覚的なダイアログを使うウィンドウ制御用。標準のダブルクリック時はこれが使われる。 |
| `CScript.exe` | Windows Script Host (CUI/コンソール版) | コマンドプロンプト内で動作する。標準入力(`StdIn`)や標準出力(`StdOut`)を直接扱える、CLIツールの主役。 |

なぜ消えてしまうのか?

Windowsの標準設定では、`.vbs` ファイルをダブルクリックすると `WScript.exe`(GUI版)で起動しようとする。しかし、コード内にコンソール向けの処理(`WScript.StdOut.Write` など)があると、OSは一時的にコンソール画面を開いて実行し、スクリプトの最後の行に到達した瞬間に、用事が済んだと判断してプロセスごと画面を閉じてしまうんだ。

これを防ぎ、ユーザーの入力を待って対話を行うためには、以下の2つのアプローチが必須になる。

1. スクリプトを最初から `CScript.exe` で実行させる
2. プログラムの最後に「入力待ち(ブロッキング処理)」を配置して、自動終了を防止する

この仕組みを、美しいコードでエレガントに実装する方法をこれから解説していくよ。

2. 対話型CUIに不可欠な「3つの神器」

コンソール画面を制御するうえで、僕たちが操作するオブジェクトは主に3つある。これらはWSHが提供する心臓部だ。

① `WScript.StdOut`(標準出力)

画面に文字を表示するためのストリーム(通り道)だ。

  • `WScript.StdOut.WriteLine(“文字列”)` : 文字列を表示して、最後に改行する。
  • `WScript.StdOut.Write(“文字列”)` : 文字列を表示するが、改行しない(「入力してください:」のようなプロンプトを作るのに最適)。

② `WScript.StdIn`(標準入力)

ユーザーがキーボードから入力した文字を受け取るためのストリームだ。

  • `WScript.StdIn.ReadLine()` : ユーザーがEnterキーを押すまでプログラムの進行を一時停止(ブロッキング)し、入力された文字列を返す。

③ `WScript.Shell`(シェルオブジェクト)

WindowsのOS機能(外部コマンドの実行など)を呼び出すための強力なCOMオブジェクトだ。今回はこれを使って「画面クリア(CLS)」を実現する。

3. 実践:画面クリア(CLS)をVBScriptで実現するテクニック

実は、VBScriptの標準機能には「画面をクリアする」というコマンドが存在しない。
そこで、`WScript.Shell` を使ってコマンドプロンプトの `cls` コマンドを内部的に呼び出すか、あるいは「画面を改行で満たす」といった工夫が必要になる。

最も確実でプロフェッショナルな方法は、`WScript.Shell` を使ってコンソールをクリアするシェルコマンドを送る方法だ。

‘ 画面をクリアするための関数例
Sub ClearScreen()
Dim objShell
Set objShell = CreateObject(“WScript.Shell”)
‘ %comspec% は cmd.exe のパスを示す環境変数です。
‘ /c は実行後にコマンドプロンプトを閉じるオプション。
‘ これにより、現在のコンソール画面に対して cls コマンドが実行されます。
objShell.Run “%comspec% /c cls”, 0, True
Set objShell = Nothing
End Sub

この「オブジェクトを作成して、使い終わったら `Nothing` で解放する」という一連の流れは、メモリ管理(ライフサイクル)において非常に重要な作法だ。初学者のうちからこの癖をつけておくと、将来複雑なシステムを組むときにメモリリーク(メモリが解放されずに溜まっていく現象)で悩まされることがなくなるよ。

4. 完全マスター:対話型CLIスクリプトの実装例

それでは、ここまでの知識をすべて詰め込んだ、「コピペでそのまま動く極上の対話型CLIツール」のコードを紹介しよう。

このスクリプトは、以下の高度な制御をすべて網羅している。

  • `CScript.exe` で実行されているかの自動チェック(不適切な起動の防止)
  • 画面のクリアと、美しいタイトルヘッダーの描画
  • ユーザーからの数値入力と、そのバリデーション(数字以外が入力されたら再入力を促す)
  • 処理終了後の「Enterキー押し待ち」による自動終了防止

【ソースコード】InteractiveCLI.vbs

‘ ==============================================================================
‘ システム名: 対話型コンソール制御スクリプト (InteractiveCLI.vbs)
‘ 開発者 : 先輩エンジニア
‘ 概要 : CScript環境下で動作し、画面クリア、バリデーション、
‘ 自動終了防止を完全に制御する対話型CLIテンプレート。
‘ ==============================================================================
Option Explicit

‘ 1. 実行環境の強制チェック (WScript.exe で起動された場合は CScript.exe で再起動)
Call ForceCScript()

‘ メイン処理の開始
Call Main()

‘ ==============================================================================
‘ メインルーチン
‘ ==============================================================================
Sub Main()
Dim userName, userAge
Dim isAgeValid

‘ 画面をクリアして初期化
Call ClearScreen()

‘ タイトルヘッダーの描画
WScript.StdOut.WriteLine “==================================================”
WScript.StdOut.WriteLine ” VBScript CLI 対話型システム v1.0 ”
WScript.StdOut.WriteLine “==================================================”
WScript.StdOut.WriteLine “”

‘ — 入力フェーズ1: お名前の入力 —
WScript.StdOut.Write “【入力 1/2】あなたのお名前を入力してください: ”
userName = WScript.StdIn.ReadLine()

‘ 未入力時のデフォルト値設定
If Trim(userName) = “” Then
userName = “名無しのシステム管理者”
End If

WScript.StdOut.WriteLine “-> ようこそ、” & userName & ” さん。”
WScript.StdOut.WriteLine “”

‘ — 入力フェーズ2: 年齢の入力 (バリデーション付きループ) —
isAgeValid = False
Do While Not isAgeValid
WScript.StdOut.Write “【入力 2/2】あなたの年齢を半角数字で入力してください: ”
userAge = WScript.StdIn.ReadLine()

‘ バリデーション: 数値であり、かつ空欄でないこと、かつ妥当な範囲であること
If IsNumeric(userAge) And Trim(userAge) <> “” Then
Dim intAge
intAge = CInt(userAge)
If intAge >= 0 And intAge <= 150 Then isAgeValid = True Else WScript.StdOut.WriteLine "[エラー] 0から150の間の正しい年齢を入力してください。" End If Else WScript.StdOut.WriteLine "[エラー] 入力値が数値ではありません。もう一度入力してください。" End If WScript.StdOut.WriteLine "" Loop ' --- 結果表示フェーズ --- Call ClearScreen() WScript.StdOut.WriteLine "==================================================" WScript.StdOut.WriteLine " 処理結果一覧 " WScript.StdOut.WriteLine "==================================================" WScript.StdOut.WriteLine "■ ユーザー名: " & userName WScript.StdOut.WriteLine "■ 年齢 : " & userAge & " 歳" WScript.StdOut.WriteLine "--------------------------------------------------" WScript.StdOut.WriteLine "データの受け付けが正常に完了しました。" WScript.StdOut.WriteLine "" ' --- 自動終了の防止 (重要!) --- ' ユーザーがEnterキーを押すまで、画面を閉じずに待機します。 WScript.StdOut.Write "【終了】Enter キーを押すと、この画面を閉じます..." WScript.StdIn.ReadLine() End Sub ' ============================================================================== ' サブルーチン・関数群 ' ============================================================================== ' 画面をクリアするサブルーチン Sub ClearScreen() Dim objShell On Error Resume Next Set objShell = CreateObject("WScript.Shell") ' cmd.exe の内蔵コマンド cls を実行 objShell.Run "%comspec% /c cls", 0, True Set objShell = Nothing On Error GoTo 0 End Sub ' 実行エンジンを CScript.exe に強制するサブルーチン Sub ForceCScript() Dim scriptHost, shellObj, args, arg, cmdLine ' 現在実行しているホスト名(WScript.exe か CScript.exe か)を取得 scriptHost = LCase(WScript.FullName) ' もし WScript.exe で実行されていたら、CScript.exe で自身を再起動する If Right(scriptHost, 11) = "wscript.exe" Then Set shellObj = CreateObject("WScript.Shell") ' 実行時に渡された引数を再構築 cmdLine = "cscript.exe //NoLogo """ & WScript.ScriptFullName & """" For Each arg In WScript.Arguments cmdLine = cmdLine & " """ & arg & """" Next ' CScript で起動し直して、現在の WScript プロセスは即座に終了する shellObj.Run cmdLine WScript.Quit End If End Sub ---

5. プロが教える!コードの裏側で起きていること

このコードには、初学者から脱却するための「プロの設計思想」がいくつか散りばめられている。特に重要なポイントを3つ、解説しよう。

① `ForceCScript` による実行環境の自己修復

このスクリプトは、ユーザーが間違えてファイルをダブルクリック(WScript起動)しても、自動的にそれを検知する。そして、裏側で「コマンドプロンプト(CScript起動)」を立ち上げ直して、自分自身をそちらに引き渡しているんだ。
ユーザーに「実行方法が違います」とエラーを吐いて終わるのではなく、プログラム側が気を利かせて勝手に最適な環境を整える。これが、業務自動化における極上のユーザーフレンドリー設計だ。

② `Do While Not isAgeValid` による無限ループ制御

ユーザーが正しい値(この場合は数値)を入力するまで、プログラムは次のステップに進まない。
`IsNumeric()` 関数を使って、入力されたデータが数値として評価できるかを厳密にチェックしている。これを「バリデーション(入力値検証)」と呼び、バグや予期せぬエラー(文字を数値に変換しようとしてプログラムがクラッシュするなど)を防ぐ最大の防御壁になる。

③ `WScript.StdIn.ReadLine()` の「ブロッキング」効果

プログラムの最後にあるこの1行が、自動終了を防ぐ最大の立役者だ。
Windowsは、この命令に到達すると「キーボードからデータ(かつEnterキー)が送られてくるまで、スレッドの一切の処理を一時停止する」という挙動をとる。これにより、処理が終わった瞬間にコンソールがスッと消えてしまうのを防ぎ、ユーザーが結果をじっくり確認できるようにしているんだ。

6. まとめ:ここをクリアすればVBScriptの基本はバッチリ!

お疲れ様! 今回は、VBScriptを使った本格的なコンソール制御について深く掘り下げて解説したよ。

今日学んだポイントをおさらいしておこう。

1. コンソール制御の主役は `CScript.exe`。
2. `WScript.StdIn.ReadLine()` は、画面の自動終了を防ぐ最強のストッパー。
3. `WScript.Shell` を経由することで、標準にはない `cls`(画面クリア)も自在に操れる。
4. 不適切な入力は、バリデーションループで徹底的に弾く。

この対話型CLIのテンプレートは、社内ツールのインストーラー、簡易的なデータ入力システム、PCの初期設定スクリプトなど、あらゆる場面に応用ができる。

マクロの記録ボタンを押すだけの世界から、自分のコードでWindowsを直接、対話的にコントロールする世界へ。君は今、確実にその一歩を踏み出した。

これからもこの調子で、楽しく、知的に自動化の世界を冒険していこう。何か分からないことがあったら、いつでもまた聞きに来ておくれ。応援しているよ!