こんにちは!VBScriptの世界へようこそ。
業務の自動化を進めていると、「VBScriptから既存のバッチファイルや外部のEXEプログラムを呼び出したい」「そして、そのプログラムが正常に終了したのか、それともエラーで失敗したのかを判定したい」という壁に必ずぶつかります。
Excelマクロの延長から一歩抜け出し、真のWindows自動化エンジニアを目指すなら、外部プロセスの「戻り値(Exit Code / ERRORLEVEL)」を完璧にハンドリングするスキルは必須です。
ここをクリアすれば、VBScriptの制御力はグッと跳ね上がりますよ。一緒に本質をマスターしていきましょう!
—
1. 外部プロセスの起動:`WScript.Shell` の二大巨頭
VBScriptから外部コマンドを叩くとき、私たちは `WScript.Shell` というオブジェクトを使います。
これには外部を呼び出す方法が2つあります。それが `.Run` メソッドと `.Exec` メソッドです。
- `Exec` メソッド: 標準入出力(stdout/stderr)を細かくキャッチしたい変態(褒め言葉です)向けの高度なメソッド。
- `Run` メソッド: コマンドラインやEXEをシンプルに呼び出し、必要なら「終了を待って、終了コードを受け取る」ことができる実用的なメソッド。
今回は、最も堅牢で現場の自動化でヘビーローテーションする `Shell.Run` の同期実行と戻り値キャッチ に焦点を当てます。
—
2. 魔法の引数 `bWaitOnReturn` の正体
`Shell.Run` の構文は以下のようになっています。
object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
ここで重要になるのが、第3引数の `bWaitOnReturn`(返却を待つかフラグ) です。
- `False` を指定した場合(非同期):
VBScriptはコマンドを投げたら、実行完了を待たずに秒速で次の行に進みます。 外部プログラムが裏で動いている最中にVBScriptが終了することもあり、エラーコードのキャッチなど不可能です。
- `True` を指定した場合(同期):
外部プログラムが処理を終えて完全に終了するまで、VBScript側の処理がその場でピタッと待機します。 そして、プログラムが吐き出した「終了コード(数値)」を、そのまま `Run` メソッドの戻り値としてスポッと返してくれるのです。
この「`True`」を指定することこそが、ERRORLEVELを完全キャッチするための絶対条件となります。
—
3. 実践!ERRORLEVEL完全キャッチコード
百聞は一見に如かず。実際に外部コマンド(今回はWindows標準の `ping` コマンドやバッチファイル)を呼び出し、終了コードによって処理を華麗に分岐させるスクリプトを見てみましょう。
メモ帳に以下のコードを貼り付け、拡張子を `.vbs`(例: `check_exitcode.vbs`)として保存して実行してみてください。
‘ ===================================================================
‘ 外部コマンドの終了コード(ERRORLEVEL)を完全制御するサンプル
‘ ===================================================================
Option Explicit
Dim objShell, intExitCode, targetHost
Set objShell = WScript.CreateObject(“WScript.Shell”)
targetHost = “127.0.0.1” ‘ 宛先(ローカルループバック)
‘ 【重要】
‘ 第1引数: 実行したいコマンド
‘ 第2引数: 0 = ウィンドウを非表示(バックグラウンド実行)
‘ 第3引数: True = 処理の完了を「待つ」(これにより戻り値が取得できる)
intExitCode = objShell.Run(“ping -n 1 ” & targetHost, 0, True)
‘ 外部コマンドから返ってきた終了コードをコンソール(またはダイアログ)で確認
WScript.Echo “外部コマンドが返した終了コード: ” & intExitCode
‘ 終了コードに基づく条件分岐(エラーハンドリング)
Select Case intExitCode
Case 0
WScript.Echo “【成功】コマンドは正常に完了しました。”
‘ ここに成功時の後続処理を書く
Case 1
WScript.Echo “【警告/想定内】処理は完了しましたが、一部警告があります。”
Case Else
‘ 0以外はすべて異常系としてハンドリング
WScript.Echo “【致命的エラー】異常終了しました。終了コード: ” & intExitCode
‘ エラーログ出力や管理者への通知処理などをここに記述
End Select
‘ クリーンアップ
Set objShell = WScript.GetDefaultContext ‘ 厳密には Set objShell = Nothing
コードのここがポイント!
1. `Option Explicit` の徹底: 変数の宣言を強制することで、タイポによる予期せぬバグを防ぎます。プロフェッショナルの基本です。
2. `intExitCode = objShell.Run(…, 0, True)`: 変数に代入している点に注目してください。`Run` の第3引数を `True` にすると、プログラムが終了した瞬間の「数値(Exit Code)」がこの変数に格納されます。
3. `Select Case` によるスマートな分岐: バッチファイルの `IF ERRORLEVEL` よりも圧倒的に美しく、保守性の高いコードになります。
—
4. 現場でありがちな「罠」と回避策
エンジニアとして現場に出ると、この `Shell.Run` でいくつかハマりポイントに遭遇します。先回りしてシェアしておきますね。
罠1: パスにスペースが含まれている場合
VBScriptで外部のEXEやバッチを叩く際、ファイルパスや引数にスペースが含まれていると、OSがパスを正しく解釈できずに即座にエラー(終了コード `1` や `2` など)を吐きます。
【対策】ダブルクォーテーションでパスを二重に囲む
Dim cmdPath
cmdPath = “””C:\My Folder\tool.exe””” ‘ 外側のダブルクォーテーションの中に内側を入れる
objShell.Run cmdPath, 1, True
VBScript内ではダブルクォーテーションを文字として扱うために `””` と重ねるテクニックが必須です。
罠2: バッチファイルを呼んだときの「落とし穴」
バッチファイル(`.bat` や `.cmd`)の中で `exit /b 99` などと書いて独自の終了コードを返そうとした場合、`cmd.exe` を経由して呼び出す必要があります。
バッチファイルを直接 `Run` しても動きますが、複雑なパスや環境を引き継がせたい場合は以下のように `cmd.exe /c` を明示するのが安全です。
intExitCode = objShell.Run(“cmd.exe /c “”C:\Scripts\my_batch.bat”””, 0, True)
これにより、バッチファイル内部で処理された `ERRORLEVEL` が、そのまま綺麗にVBScript側の `intExitCode` へ引き渡されます。
—
5. おわりに
いかがでしょうか?
「ただプログラムを動かす」から「プログラムの意思(終了コード)を受け取って、VBScript側で知的に制御する」へステップアップできたのではないでしょうか。
この `Shell.Run` の `bWaitOnReturn` の制御をマスターすれば、日々のファイル整理バッチ、データベースのバックアップスクリプト、他システム連携のキック処理など、業務自動化でできないことはほぼなくなります。
ここをクリアしたあなたなら、もうVBScriptの基礎はバッチリです!自信を持って、現場の自動化をガンガン進めていってくださいね。応援しています!
