VBScriptを掌握せよ:WScript.Shellにおける「Run」と「Exec」の深淵なる使い分け
VBScriptは、もはや「過去の遺物」などではない。Windowsという巨大なOSの深層で、今なお軽量かつ強力に駆動し続ける、不可欠な自動化の武器である。
多くのエンジニアが「コマンドを実行する」という単純な目的に対し、`WScript.Shell`の `Run` と `Exec` を適当に使い分けている。だが、その選択がシステムの安定性を左右することを知っている者は少ない。本稿では、レガシー環境の保守からエンタープライズな自動化までを支える、プロフェッショナルのための「外部コマンド実行の極意」を伝授する。
—
1. Runメソッド:戻り値(ExitCode)を重んじる「同期」の正解
`WScript.Shell.Run` は、プロセスの実行結果(終了コード)を得るための最も堅牢な手段だ。
Runの哲学
- 同期実行 (`bWaitOnReturn = True`) を指定することで、親スクリプトは外部コマンドの終了まで完全に待機する。
- 戻り値として「プロセスの終了コード(ERRORLEVEL)」を直接受け取れる。
- 注意点: `Run` は標準出力(StdOut)をキャプチャできない。結果をファイルにリダイレクトして読み込むか、終了コードのみで判断が必要な処理に限定すべきだ。
‘ — Runメソッドによる同期実行の模範 —
Dim oShell, nExitCode
Set oShell = CreateObject(“WScript.Shell”)
‘ 第2引数: 0=非表示, 第3引数: True=終了まで待機
nExitCode = oShell.Run(“cmd.exe /c exit 100”, 0, True)
If nExitCode = 100 Then
WScript.Echo “成功: 特定の終了コードを検知”
Else
WScript.Echo “失敗: エラーコード ” & nExitCode
End If
‘ オブジェクトの明示的解放はメモリ管理の鉄則
Set oShell = Nothing
—
2. Execメソッド:標準出力を掌握する「パイプライン」の極み
外部コマンドの実行結果(テキスト情報)を解析する必要がある場合、`WScript.Shell.Exec` 一択である。
Execの哲学
- ストリームの直接接続: `Exec` は `WshScriptExec` オブジェクトを返し、そこから `StdOut` プロパティを介してパイプラインを読み取れる。
- 非同期の罠: `Exec` は常に非同期で起動する。`Status` プロパティを監視するか、`ReadAll` を呼び出して終了まで待機する設計が不可欠だ。
‘ — Execメソッドによる標準出力キャプチャの模範 —
Dim oShell, oExec, sOutput
Set oShell = CreateObject(“WScript.Shell”)
‘ Execは同期オプションを持たない。終了を待機する設計が必要
Set oExec = oShell.Exec(“powershell.exe -Command “”Get-Date -Format ‘yyyy-MM-dd'”””)
‘ 終了するまで待機(ReadAllはストリームがクローズされるまでブロックする)
sOutput = oExec.StdOut.ReadAll
‘ 終了コードの確認
If oExec.ExitCode = 0 Then
WScript.Echo “取得結果: ” & Trim(sOutput)
Else
WScript.Echo “エラー発生: ” & oExec.StdErr.ReadAll
End If
‘ 明示的な解放
Set oExec = Nothing
Set oShell = Nothing
—
3. なぜ「オブジェクトの解放」に執着するのか
VBScriptのメモリ管理は参照カウンタ方式だ。スクリプトが終了すれば解放されるのは事実だが、長時間稼働するWSHのタスクや、大規模なループ処理の中でオブジェクトを生成・破棄する場合、`Set oShell = Nothing` を怠ればメモリリークの温床となる。
特に `Exec` はサブプロセスを生成する。親スクリプトが終了しても、子のストリームが閉じられていない場合、ゾンビプロセスが残存するリスクがある。「生成したものは必ず消す」。この泥臭い習慣こそが、数年単位で止まらないシステムを作る秘訣だ。
—
4. チーフアーキテクトからの提言:どちらを選ぶべきか
現場の判断基準は極めてシンプルである。
1. 「結果のテキスト」が不要で、成功/失敗だけが重要な場合
→ `Run` を使え。 システム負荷が低く、シンプルで、ERRORLEVELのハンドリングが最も確実だ。
2. 「出力された情報」をパースして次の処理に活かす場合
→ `Exec` を使え。 ただし、`StdErr`(標準エラー出力)の監視を忘れるな。`StdOut` だけを読んで `StdErr` を放置すると、バッファ溢れによりコマンドがハングアップすることがある。
最後に
VBScriptは、APIの複雑な隠蔽がない分、OSの挙動をダイレクトに叩ける「極めて正直な言語」だ。WScript.Shellを完全に掌握した時、君はWindowsのあらゆるレガシーシステムを意のままに操る力を手に入れることになる。
環境の限界を嘆くのではなく、その環境でいかに美しく、堅牢なコードを書くか。それこそが、我々エンジニアが追求すべき真の技術的到達点である。
