ネットワークアダプタの生殺与奪権を掌握する:WMI/VBScriptによる極限制御
システム管理の現場において、ネットワークインターフェースカード(NIC)の物理的な抜き差しや、GUIをポチポチと叩く作業は「素人」の仕事だ。我々エンジニアが対峙すべきは、障害検知から即座に切り替わるフェイルオーバー、あるいはセキュリティポリシによる動的な回線遮断という「自動化の極致」である。
今回は、WSH(Windows Script Host)の心臓部であるWMI(Windows Management Instrumentation)を叩き、`Win32_NetworkAdapter`を通じてNICの有効・無効を制御する、枯れ切った、しかし最強の手段を伝授する。
—
1. 概念の深淵:WMIの「重さ」と向き合う
VBScriptでWMIを扱う際、多くの初心者は「インスタンスを呼び出して終わり」と考えている。だが、実戦ではオブジェクトのライフサイクル管理がシステムの寿命を左右する。
- 単一責務の原則: スクリプト内で全てのNICを列挙して条件分岐させるな。一意の識別子(`DeviceID`または`Name`)を外部パラメータから受け取り、ピンポイントでオブジェクトをバインドせよ。
- メモリ解放の義務: VBScriptのガベージコレクションを信用するな。`Set obj = Nothing` を怠ることは、長期間稼働する監視スクリプトにおけるメモリリークの温床だ。
—
2. 実装コード:NIC制御の決定版
このコードは、指定したNIC名がシステムに存在する場合に、その状態をトグルあるいは指定値へ強制遷移させるためのものだ。管理者権限(UAC)が必須であることは言うまでもない。
‘ — NIC制御用ユーティリティ: NetworkController.vbs —
Option Explicit
‘ 制御対象のNIC名(正確に指定すること)
Const TARGET_NIC_NAME = “Intel(R) Ethernet Connection”
‘ 操作: 1 = Enable, 2 = Disable
Const OPERATION_CODE = 2
Call ToggleNetworkAdapter(TARGET_NIC_NAME, OPERATION_CODE)
Sub ToggleNetworkAdapter(strNicName, intAction)
Dim objWMIService, colAdapters, objAdapter, errResult
‘ WMI接続: ローカルホストのCIMV2ネームスペースへ接続
Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)
‘ WQLクエリ: 対象を特定。NetConnectionIDはGUI上の名前と一致する
Set colAdapters = objWMIService.ExecQuery _
(“SELECT FROM Win32_NetworkAdapter WHERE NetConnectionID = ‘” & strNicName & “‘”)
If colAdapters.Count = 0 Then
WScript.Echo “対象のアダプタが見つかりません: ” & strNicName
Exit Sub
End If
For Each objAdapter In colAdapters
If intAction = 1 Then
errResult = objAdapter.Enable()
Else
errResult = objAdapter.Disable()
End If
‘ 結果判定: 0は成功を意味する
If errResult = 0 Then
WScript.Echo “成功: ” & strNicName & ” の操作を実行しました。”
Else
WScript.Echo “エラー: 制御に失敗しました。戻り値: ” & errResult
End If
Next
‘ メモリ最適化: 明示的な参照解除
Set colAdapters = Nothing
Set objWMIService = Nothing
End Sub
—
3. シニアエンジニアが押さえるべき「罠」
このスクリプトを実環境へ投入する際、必ず遭遇する壁がある。
① UACと権限昇格の壁
WMIの `Enable`/`Disable` メソッドは、特権プロセスでなければ確実に `Access Denied`(戻り値 5)を吐く。バッチファイルから呼び出す場合は、以下のコマンドでスクリプトをセルフホストして昇格させる「おまじない」が必要だ。
:: 昇格実行用ラッパー
@echo off
net session >nul 2>&1
if %errorLevel% neq 0 (
powershell -Command “Start-Process ‘%~f0’ -Verb RunAs”
exit /b
)
cscript //nologo NetworkController.vbs
② NetConnectionIDの落とし穴
`Win32_NetworkAdapter` の `Name` プロパティはドライバ名を示すことが多いが、`NetConnectionID` はコントロールパネルのネットワーク接続に表示される名前だ。環境によって言語設定やOSの更新で文字列が揺れるため、運用開始前に必ず `wmic nic get NetConnectionID` で正確な文字列を抽出して定義すること。
③ 非同期実行のラグ
`Enable` メソッドを叩いた直後にネットワーク通信を試みても、TCP/IPスタックの初期化が追いつかず失敗する。自動化フローの中に組み込む場合は、`WScript.Sleep 5000` 程度のバッファを挟むか、`Win32_NetworkAdapterConfiguration` の `IPEnabled` プロパティをポーリングして、真に通信可能になるまで待機するループを実装するのがプロの流儀だ。
—
結びに代えて
VBScriptは「レガシー」などではない。OSの深層に直接触れ、数行のコードでシステム全体を制御できる、極めて軽量かつ強力なアーキテクチャである。過剰なフレームワークに頼らず、OSが提供するAPIの核心を突くこと。それこそが、時代が変わっても揺るがない「エンジニアの価値」である。
次は、このスクリプトをタスクスケジューラと組み合わせ、特定のイベントログをトリガーに自己修復する監視エージェントの構築について語ろう。健闘を祈る。
