VBScriptでネットワークを制御する:WMIを用いた動的メトリック変更の極意
現場で「有線と無線が切り替わらない」「特定の通信だけ遅延する」という課題に直面したことはないか? Windowsのネットワークスタックは優秀だが、マルチホーム環境においてはしばしば判断を誤る。
今回は、WMI(Windows Management Instrumentation)の深淵を覗き、`Win32_IP4RouteTable` を直接操作してネットワークの優先順位を物理的にねじ伏せる、極めて実用的な自動化手法を伝授する。
—
1. なぜWMI操作なのか:ルーティング制御の本質
OSのルーティングテーブルは、単なる優先順位のリストではない。各経路には「メトリック値」が割り当てられており、値が小さいほど「近道」と見なされる。
多くの現場で行われる「アダプター設定からのメトリック手動変更」は、数台なら良い。だが、数百台規模の環境でこれをやるのは、エンジニアとしての敗北だ。我々はスクリプトでこれを制御し、環境の変化に合わせて動的にルートを再定義する。
避けるべき非効率なアプローチ
- `route change` コマンドの多用: 外部プロセスを何度も叩くのは、プロセス生成のオーバーヘッドが大きく、不安定だ。
- WScript.Shellの過信: ネットワークインターフェースのインデックス(IfIndex)は再起動や接続状況で変動する。固定値でハードコーディングするのは愚の骨頂である。
—
2. プロダクションコード:動的メトリック変更スクリプト
このコードは、指定したネットワークインターフェースのメトリック値を安全に更新する設計だ。
‘ — ネットワークルート自動切り替えエンジンのコア —
Option Explicit
Const WMI_NAMESPACE = “root\cimv2”
Const TARGET_DEST = “0.0.0.0” ‘ デフォルトゲートウェイを対象とする
‘ 実行例: 有線LAN(InterfaceIndex 12)のメトリックを10に変更する
UpdateRouteMetric 12, 10
Sub UpdateRouteMetric(ifIndex, newMetric)
Dim objWMIService, colRoutes, objRoute
Dim strQuery
Set objWMIService = GetObject(“winmgmts:\\.\” & WMI_NAMESPACE)
‘ 指定したインターフェースかつデフォルトルートを特定
strQuery = “SELECT FROM Win32_IP4RouteTable WHERE Destination='” & TARGET_DEST & “‘ AND InterfaceIndex=” & ifIndex
Set colRoutes = objWMIService.ExecQuery(strQuery)
If colRoutes.Count = 0 Then
WScript.Echo “対象ルートが見つかりません。Indexが正しいか確認してください。”
Exit Sub
End If
For Each objRoute In colRoutes
‘ メトリックの更新(WMIのメソッドではなく、Setメソッドでプロパティを更新)
‘ 注意: Win32_IP4RouteTable は読み取り専用属性が多い場合、
‘ 必要に応じて SetGateWay メソッドや Network アダプター側の設定変更を併用すること
WScript.Echo “Routing: ” & objRoute.Destination & ” -> Metric: ” & newMetric
‘ 実際の実装では、ここで netsh を併用する設計が最も堅牢
‘ WMIは情報の取得には最強だが、書き込みに関してはOSの権限保護が強固であるため
Dim shell: Set shell = CreateObject(“WScript.Shell”)
shell.Run “netsh int ip set interface ” & ifIndex & ” metric=” & newMetric, 0, True
Next
End Sub
—
3. 開発現場における「絶対守るべき鉄則」
① 権限の壁を理解する
WMI経由であれ `netsh` であれ、ネットワーク設定の変更は管理者権限(Elevated Privilege)が必須だ。VBScriptをタスクスケジューラで走らせる際は、「最上位の権限で実行する」にチェックを入れることを忘れるな。これを怠ると、スクリプトは沈黙したまま何も起きない。
② IfIndexの動的解決
ハードコーディングは諸悪の根源だ。必ず `Win32_NetworkAdapter` クラスを事前にクエリし、`NetConnectionID`(”イーサネット”や”Wi-Fi”といった名称)から現在の `InterfaceIndex` を動的に取得するロジックを前段に置け。
③ ログと排他制御
ファイルやDBに状態を書き込む際は、必ずエラーハンドリングを入れること。
On Error Resume Next
‘ 処理…
If Err.Number <> 0 Then
‘ ログファイルへ書き出し
WriteLog “Critical Error: ” & Err.Description
End If
On Error GoTo 0
これがないスクリプトは、夜中に原因不明で停止し、翌朝のヘルプデスクを地獄に突き落とす。
—
4. 最後に:エンジニアとしての矜持
VBScriptは「古い」と言われることがある。だが、Windowsという巨大なOSの深部を、外部ライブラリなしで直接叩けるこの言語は、業務自動化のラストリゾートとして今なお最強だ。
今回紹介した手法をベースに、さらに「Pingによる死活監視」や「SSID情報の取得」を組み合わせれば、君の現場だけの「インテリジェントなネットワーク制御」が完成する。
自動化とは、ただ楽をすることではない。「人間が判断しなくても済む状況を、堅牢なコードで作り上げること」だ。自信を持って、コードを書き進めてほしい。
