【入門編】【マルチタスク依存関係制御】WScript.Shell を用いた複数バッチ・スクリプトの実行順序制御タスクランナー – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、自分の手でWindowsのシステムを自在に操るエンジニアの扉を開こうとしているあなたを、心から歓迎します。

さて、現場でこんな悩みにぶつかったことはありませんか?
「複数のバッチファイルやスクリプトを順番に動かしたいけれど、Aが完全に終わってからBを動かしたい。しかも、途中でAがエラーを起こしたら、Bを動かさずに安全に止まってほしい……」

Excelのマクロや単純なバッチファイルでは、こうした「プロセスの依存関係(順序制御)」を綺麗にハンドリングするのは至難の業です。しかし、Windows標準のWScript.Shellを使いこなせば、VBScriptだけで堅牢なワークフローエンジン(タスクランナー)を構築できてしまいます。

今回は、現場のエンジニアがこっそり使っている「複数プロセスの制御術」を、優しく、そして徹底的に解説していきましょう。ここをクリアすれば、あなたのVBScriptのスキルは間違いなく一段上のステージに到達しますよ!

1. なぜ「WScript.Shell」と「Runメソッド」なのか?

VBScriptから外部のプログラム(バッチファイルやEXEなど)を呼び出す際、主役になるのが `WScript.Shell` オブジェクトです。

その中でも、プロセス制御の鍵を握るのが `Run` メソッド です。
よくある単純な実行コードだと、スクリプトは外部プロセスの終了を待たずに次の行へ進んでしまいます(非同期実行)。これでは「Aが終わってからB」という順番が守れません。

`Run` メソッドの第3引数に `True` を指定することで、「外部プロセスの処理が完全に終わるまで、VBScript側の実行をピタッと待たせる(同期実行)」 ことができるようになります。これが、依存関係制御のすべての土台となります。

基本の構文イメージ

Set objShell = CreateObject(“WScript.Shell”)
‘ 第3引数を True にすることで、プロセスの終了を待ち合わせる
‘ 戻り値には、実行したプログラムの「終了コード(Exit Code)」が返る
intExitCode = objShell.Run(“C:\path\to\batch.bat”, 0, True)

この「終了コード(Exit Code)」というのが非常に重要です。プログラムが正常終了したときは `0`、エラーで異常終了したときは `0` 以外の数字(`1` や `-1` など)が返ってくるのが一般的なお作法です。これを利用して、「エラーが起きたら次の処理をスキップする」という判断ができるわけです。

2. 実践!依存関係を制御するワークフローエンジンの構築

百聞は一見に如かず。実際に「タスクA ➔ タスクB ➔ タスクC」という依存関係を持ち、途中で失敗したら後続を止めて安全に離脱する実用的なタスクランナーのコードを見てみましょう。

メモ帳を開いて、以下のコードを `task_runner.vbs` という名前で保存してみてください。

‘ ==============================================================================
‘ スクリプト名: WorkflowTaskRunner.vbs
‘ 概要: 複数のバッチファイルを依存関係順に実行し、エラー時は処理を中断するタスクランナー
‘ ==============================================================================

Option Explicit

‘ エラーハンドリングの準備
On Error Resume Next

Dim objShell, intResult
Set objShell = CreateObject(“WScript.Shell”)

If Err.Number <> 0 Then
WScript.Echo “致命的なエラー: WScript.Shellの生成に失敗しました。”
WScript.Quit 1
End If

On Error GoTo 0 ‘ 標準のエラー処理に戻す

WScript.Echo “=== ワークフロー処理を開始します ===”

‘ ——————————————————————————
‘ 【ステップ 1】環境初期化バッチの実行
‘ ——————————————————————————
WScript.Echo “[STEP 1] 環境初期化タスクを実行中…”

‘ 第2引数の「0」はウィンドウ非表示(バックグラウンド実行)
‘ 第3引数の「True」は終了同期
intResult = objShell.Run(“cmd.exe /c “”C:\Work\step1_init.bat”””, 0, True)

‘ 終了コードをチェック
If intResult <> 0 Then
WScript.Echo “[ERROR] ステップ1で異常終了しました。終了コード: ” & intResult
WScript.Echo “ワークフローを中断します。”
WScript.Quit intResult ‘ 異常終了ステータスを返して終了
End If

WScript.Echo “[SUCCESS] ステップ1が正常終了しました。”

‘ ——————————————————————————
‘ 【ステップ 2】データ処理バッチの実行
‘ ——————————————————————————
WScript.Echo “[STEP 2] メインデータ処理タスクを実行中…”

intResult = objShell.Run(“cmd.exe /c “”C:\Work\step2_process.bat”””, 0, True)

If intResult <> 0 Then
WScript.Echo “[ERROR] ステップ2で異常終了しました。終了コード: ” & intResult
WScript.Echo “ワークフローを中断します。”
WScript.Quit intResult
End If

WScript.Echo “[SUCCESS] ステップ2が正常終了しました。”

‘ ——————————————————————————
‘ 【ステップ 3】後片付け・通知バッチの実行
‘ ——————————————————————————
WScript.Echo “[STEP 3] 終了処理および通知タスクを実行中…”

intResult = objShell.Run(“cmd.exe /c “”C:\Work\step3_cleanup.bat”””, 0, True)

If intResult <> 0 Then
WScript.Echo “[WARNING] ステップ3で警告あり。終了コード: ” & intResult
‘ ここは重要度に応じて続行するか決める(今回は警告として続行例)
End If

WScript.Echo “=== すべてのワークフローが正常に完了しました ===”

‘ オブジェクトの解放(メモリのクリーンアップ)
Set objShell = Nothing
WScript.Quit 0

3. コードの深い部分を読む:プロが仕込む「安全装置」

上記のコードには、現場で生き残るためのVBScriptの知見がいくつか詰まっています。ポイントを解説しましょう。

① `Option Explicit` による変数の厳格化

これを冒頭に書くことで、変数宣言のし忘れ(タイポによるバグ)を防げます。プログラミングの基本中の基本ですが、VBScriptではこれをサボると原因不明の変な挙動に悩まされるため、必ずセットで書きましょう。

② `cmd.exe /c` を挟むテクニック

`objShell.Run` でバッチファイルを直接叩くのではなく、`cmd.exe /c “パス”` という形式で呼び出している点に注目してください。
バッチファイル特有のパスの解釈や、環境変数の引き継ぎトラブルを防ぎ、確実にプロセスを安全に起動するためのシニアエンジニアの定石テクニックです。パスの中にスペースが含まれる場合があるため、ダブルクォーテーションの重ね方(`””`)にも注意してくださいね。

③ オブジェクトの明示的な解放 (`Set objShell = Nothing`)

VBScriptのガベージコレクタは優秀ですが、COMオブジェクト(`WScript.Shell`など)を大量に生成・破棄するような複雑なスクリプトでは、プロセスが終了する前に明示的にメモリを解放する癖をつけておくと、メモリリークやファイルロックのトラブルを未然に防げます。

4. 陥りやすい罠とエラー回避の極意

初心者がこの領域で必ずハマる「典型的な罠」をいくつかご紹介しておきます。

  • 罠1:パスにスペースが含まれていて起動しない
  • 原因: `C:\Program Files\App\run.bat` のようにスペースがあると、OSが途中でパスを勝手に区切ってしまい「ファイルが見つかりません」エラーになります。
  • 対策: 先ほどのコード例のように、実行コマンド全体をダブルクォーテーションで囲む癖をつけましょう(例: `objShell.Run “””C:\Program Files\App\run.bat”””, 0, True`)。
  • 罠2:バッチ側でエラーが起きているのにVBScript側が「成功」と判定してしまう
  • 原因: バッチファイル内でエラーが発生しても、バッチ自体の最後のコマンドが正常終了していれば、終了コードとして `0` が返ってきてしまうことがあります。
  • 対策: 呼び出される側のバッチファイルでも、エラー発生時に明示的に `exit /b 1` などを返すように設計しておく必要があります。タスクランナーと子バッチはチームワークです!

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

今回は、`WScript.Shell` の同期実行と終了コードのハンドリングを軸にした「マルチタスク依存関係制御タスクランナー」の構築手法を解説しました。

単にコードを上から下に流すだけでなく、
1. 外部プロセスの終了を正しく待つ (`True`)
2. 戻り値(終了コード)を監視する
3. 異常があれば安全に処理を中断 (`WScript.Quit`) する

この3つの原則さえ押さえておけば、どんなに複雑な業務自動化のフローであっても、VBScriptで美しく制御することができます。

マクロの記録の枠を飛び出し、Windowsの隅々までコントロールできる楽しさを、ぜひあなたの開発現場でも味わってみてください。応援しています!

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