VBScriptでネットワークアダプタを制する:WMI制御の極限と堅牢な自動化設計
現場の自動化において、WMI (Windows Management Instrumentation) は諸刃の剣だ。正しく扱えば強力なインフラ操作ツールとなり、一歩間違えればシステムに深刻な不整合をもたらす。
今回は、ネットワークアダプタの有効化・無効化という、一見単純だが「ミスが許されない」制御を題材に、VBScriptによるプロフェッショナルな実装術を授ける。
—
1. なぜ「単純なコード」では現場で通用しないのか
多くの初心者は、ネットで見つけた `objAdapter.Enable()` をそのまま書く。だが、プロダクション環境では以下の3つの壁に突き当たる。
1. 非同期処理の罠: WMIのメソッド呼び出しは即座に終了するが、OS側のNIC切り替えは完了していない。連続して制御を行うと競合が発生する。
2. 特権の不備: NICの制御には管理者権限が必須だ。スクリプトが昇格しているかを確認する防衛的コードがないと、ツールは無言で失敗する。
3. アダプタの曖昧性: `Name` プロパティだけで特定するのは危険だ。ドライバ名や仮想アダプタが混在する環境では、必ず `DeviceID` や `PNPDeviceID` をキーにすべきだ。
—
2. 堅牢なネットワーク制御スクリプト実装
以下は、保守性と安全性を極限まで高めた実装例だ。アダプタの名称を正規表現的、あるいは部分一致で判定し、処理結果を確実に取得する構成としている。
‘ ==============================================================================
‘ NetworkAdapterController.vbs
‘ 用途: 特定のネットワークアダプタの有効化/無効化を制御する
‘ ==============================================================================
Option Explicit
‘ 設定項目:対象のアダプタ名(部分一致で検索)
Const TARGET_ADAPTER_NAME = “Wi-Fi”
Const ACTION_ENABLE = True ‘ True:有効, False:無効
Call Main()
Sub Main()
Dim objWMIService, colAdapters, objAdapter, errResult
‘ 1. 管理者権限のチェック(簡易的ですが実務では必須)
If Not IsAdmin() Then
WScript.Echo “エラー: このスクリプトは管理者権限で実行してください。”
WScript.Quit 1
End If
‘ 2. WMIサービスへの接続
Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)
‘ 3. アダプタの検索(NetConnectionStatusがNullでない物理デバイスを対象にするのがコツ)
Set colAdapters = objWMIService.ExecQuery _
(“SELECT FROM Win32_NetworkAdapter WHERE NetConnectionID LIKE ‘%” & TARGET_ADAPTER_NAME & “%'”)
If colAdapters.Count = 0 Then
WScript.Echo “対象のアダプタが見つかりません: ” & TARGET_ADAPTER_NAME
Exit Sub
End If
For Each objAdapter In colAdapters
WScript.Echo “処理中: ” & objAdapter.NetConnectionID
If ACTION_ENABLE Then
errResult = objAdapter.Enable()
Else
errResult = objAdapter.Disable()
End If
‘ 4. エラーハンドリング:0は成功
If errResult = 0 Then
WScript.Echo “成功: ステータスを更新しました。”
Else
WScript.Echo “失敗: エラーコード ” & errResult & ” が発生しました。”
End If
Next
End Sub
‘ 管理者権限確認関数
Function IsAdmin()
Dim shell: Set shell = CreateObject(“WScript.Shell”)
On Error Resume Next
shell.RegRead “HKEY_USERS\S-1-5-19\”
If Err.Number = 0 Then IsAdmin = True Else IsAdmin = False
On Error GoTo 0
End Function
—
3. 実務で運用するための「3つの鉄則」
① ログ出力の外部化
上記のコードでは `WScript.Echo` を使用しているが、これをそのままバッチファイルにリダイレクトしてはいけない。
テキストファイルにタイムスタンプ付きで出力する関数を別途用意し、どの端末でいつ切り替えが発生したかを追跡できるようにせよ。これは障害調査時の生命線となる。
② データベース/設定ファイル連携
アダプタ名は環境によって異なる可能性がある。ハードコードを避け、`config.ini` や `settings.json` を読み込み、対象アダプタを外部から注入できるように設計すべきだ。VBScriptでは `Scripting.FileSystemObject` を使い、簡単なINIファイルを読み込むのが最も堅牢でポータブルである。
③ WMIクエリの最適化
`SELECT ` は思考停止の証だ。必要なプロパティ(`NetConnectionID`, `DeviceID`, `NetEnabled`)のみを指定することで、メモリ消費を抑え、ネットワーク機器が多数存在する環境での動作速度を向上させることができる。
—
アーキテクトからの助言
VBScriptは「古い言語」と揶揄されることもあるが、OSの深いレイヤーに直接触れられるという点において、PowerShellにも負けない即応性がある。
重要なのは、コードの書き方以上に「失敗したときにどうリカバリするか」という設計思想だ。もし無効化処理が途中でコケたら、対象端末は孤立する。スクリプトを走らせる際は、必ず「制御不能に陥った際の緊急アクセス手段」を確保した上で実行せよ。
現場の自動化は、完璧なコードよりも、リスクに対する冷徹な視点から生まれるのだ。
