【入門編】【ネットワーク診断】WMI (Win32_PingStatus) を活用した複数拠点への並列 Ping 確認とパケット損失率の自動集計 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

脱・初心者!`ping.exe`を卒業してWMIでネットワーク診断を極める:構造化データによるプロフェッショナルな自動化

こんにちは。現場の最前線で自動化の設計(アーキテクチャ)を司っているエンジニアです。

「VBScriptでネットワークの疎通確認を作りたい」と思ったとき、多くの人が最初に思い浮かべるのは、おそらくこのコードではないでしょうか。

' 初心者がやりがちな、外部コマンド呼び出しの例
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "ping 192.168.1.1", 0, True

もちろん、これは間違いではありません。しかし、もしあなたが「業務で使える、堅牢で、メンテナンスしやすいツール」を目指すなら、この方法は「避けるべき落とし穴」です。

なぜなら、`ping.exe`の結果は「ただのテキスト(文字列)」だからです。OSの言語設定が日本語から英語に変わっただけで、文字列の解析(パース)に失敗し、システムが止まってしまう……。そんな脆いコードを、プロフェッショナルは書きません。

今日は、Windowsの深淵に眠る強力な仕組み「WMI (Windows Management Instrumentation)」を使い、ネットワーク状態を「数値」や「真偽値」として直接、美しく取得する方法を伝授しましょう。ここをクリアすれば、あなたのVBScriptは「マクロ」から「システムツール」へと進化します。

1. なぜ「WMI」を使うのか? テキスト解析の呪縛から解き放たれる

プログラミングにおける最大の敵は「不確実性」です。

外部コマンド(`ping.exe`)の結果を扱う場合、あなたは「返ってきた文字列の中から、応答時間(ms)が書かれている場所を探し、数字だけを切り出す」という、非常に面倒で壊れやすい作業(パース)を強いられます。

対してWMIは、Windows OSが持っている「管理情報」に直接アクセスするインターフェースです。

  • `ping.exe`の場合: 「応答 = 10ms」という「文章」が返ってくる。
  • WMIの場合: `ResponseTime = 10` という「数値データ」が返ってくる。

データが「構造化」されている。この違いこそが、自動化エンジニアがWMIを愛してやまない理由です。

2. 実践:複数拠点へのPing確認とパケット損失率の集計ツール

それでは、実際に「複数のIPアドレスに対して、それぞれ4回ずつPingを打ち、パケット損失率を算出する」という実戦的なスクリプトを書いてみましょう。

このコードは、単なる疎通確認ではなく、「ネットワークの品質(パケットロス)」までを可視化する設計にしています。

' ==============================================================================
' ネットワーク診断ツール (WMI版)
' 機能: 指定した複数拠点に対し、パケットロス率を含むネットワーク状態をレポート
' ==============================================================================
Option Explicit

' --- 設定エリア ---
Dim targetList
' 診断したいIPアドレスやホスト名を配列で定義します
targetList = Array("8.8.8.8", "1.1.1.1", "127.0.0.1", "192.168.254.254")

Dim pingCount
' 1拠点あたりに送信するパケット数(損失率を計算するために複数回実行)
pingCount = 4
' ------------------

Dim objWMIService, objPing, strQuery
Dim target, i, successCount, responseTimeSum, lossRate
Dim strReport

' WMIサービスの取得 (Windowsの管理情報の入り口)
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

strReport = "--- ネットワーク診断レポート ---" & vbCrLf & _
            "実行日時: " & Now & vbCrLf & vbCrLf

' 各ターゲットに対してループ処理
For Each target In targetList
    successCount = 0
    responseTimeSum = 0
    
    ' WMIの Win32_PingStatus クラスを使用して、Pingを実行するクエリを作成
    ' Address プロパティで対象を指定します
    strQuery = "SELECT * FROM Win32_PingStatus WHERE Address = '" & target & "'"
    
    ' 指定した回数分、Pingを試行
    For i = 1 To pingCount
        Set objPing = objWMIService.ExecQuery(strQuery)
        
        ' 結果の検証
        ' ExecQueryはコレクションを返すため、For Eachで中身を取り出す
        For Each obj In objPing
            ' StatusCode が 0 であれば成功
            If Not IsNull(obj.StatusCode) And obj.StatusCode = 0 Then
                successCount = successCount + 1
                responseTimeSum = responseTimeSum + obj.ResponseTime
            End If
        Next
        
        ' 連続実行時のわずかな待ち時間(CPU負荷軽減と精度のため)
        WScript.Sleep 100 
    Next
    
    ' --- 統計計算 ---
    ' 損失率 = (試行回数 - 成功回数) / 試行回数 * 100
    lossRate = ((pingCount - successCount) / pingCount) * 100
    
    ' 平均応答時間の計算(成功時のみ)
    Dim avgResponse
    If successCount > 0 Then
        avgResponse = Round(responseTimeSum / successCount, 2) & " ms"
    Else
        avgResponse = "N/A"
    End If

    ' レポート行の組み立て
    strReport = strReport & "Target: " & Left(target & Space(15), 15) & _
                " | Loss: " & Right(lossRate & Space(5), 5) & "%" & _
                " | Avg RTT: " & Left(avgResponse & Space(10), 10) & vbCrLf
Next

' 結果の出力
WScript.Echo strReport

' --- オブジェクトの解放 (ライフサイクル管理) ---
' メモリリークを防ぐため、使い終わったオブジェクトは明示的にNothingを代入します
Set objWMIService = Nothing
Set objPing = Nothing

3. コードの核心:アーキテクトの視点から解説

このコードを理解するために、重要な3つのポイントを解説します。

① WMIへの接続とNamespace

`GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2”)`

ここが魔法の入り口です。`root\cimv2` というのは、Windowsの標準的な管理情報が格納されている「名前空間(Namespace)」です。`impersonationLevel=impersonate` は、「実行しているユーザーの権限を使って操作する」というセキュリティ的な宣言です。これを適切に設定することで、システムへのアクセス権を制御しています。

② `Win32_PingStatus` の活用

`strQuery = “SELECT * FROM Win32_PingStatus WHERE Address = ‘…'”`

SQL(データベース言語)に似た書き方をするのがわかりますか? これがWMIの強力なところです。「`Win32_PingStatus` というテーブルから、`Address` がこれに一致するデータを持ってきてくれ」と命令しているのです。
取得できるデータは、`StatusCode`(成否)、`ResponseTime`(応答速度)といった数値型です。これにより、`If obj.StatusCode = 0 Then` といった、極めてシンプルで堅牢な条件分岐が可能になります。

③ オブジェクトのライフサイクル(重要!)

コードの最後にある `Set obj = Nothing`。
これは初心者の方が最も見落としがちな、しかしプロが最も重視する作法です。VBScriptは「参照カウンタ」によってメモリを管理していますが、ループ内で大量のWMIオブジェクトを生成し続けると、メモリを食いつぶしたり、システムのリソースを占有し続けたりすることがあります。
「作ったものは、使い終わったら捨てる」。これが、安定した自動化ツールを作る鉄則です。

4. 陥りやすいエラーと対策

このツールを運用する上で、以下の点に注意してください。

1. 権限エラー (Access Denied):
WMIへのアクセスには、実行ユーザーに適切な権限が必要です。管理者権限でコマンドプロンプトから実行するか、適切なユーザー権限を持つ環境で実行してください。
2. タイムアウトの問題:
ネットワークが極端に遅い、あるいは相手が完全にダウンしている場合、WMIの応答待ちでスクリプトが止まったように見えることがあります。実務では、`WScript.Sleep` を適切に挟む、あるいはタイムアウト設定を考慮する設計が必要です。
3. 「並列」の勘違い:
VBScript自体はシングルスレッド(一度に一つのことしかできない)です。上記のコードは「順番に」実行しています。もし数千台のサーバーを同時にチェックしたい場合は、VBScriptを複数個同時に立ち上げる(分身させる)といった、別の設計思想が必要になります。

まとめ:ここをクリアすれば、基本はバッチリです

いかがでしたでしょうか?
`ping.exe` という「道具」を使うのではなく、WMIという「仕組み」を操作する。この視点の切り替えこそが、初級者と中級者、そしてプロフェッショナルを分ける境界線です。

  • テキストを解析するな、データを取得せよ。
  • オブジェクトのライフサイクルを意識せよ。
  • エラーを想定し、堅牢なコードを書け。

この3点を意識するだけで、あなたの書くスクリプトの品質は劇的に向上します。
さあ、次はあなた自身の手で、このコードを拡張して「ログファイル出力機能」や「異常検知時のメール通知機能」を追加してみてください。そこから、あなたの真のエンジニアとしての旅が始まります。

応援していますよ!

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