【VBA×WMI】リモートPCのシステム情報(OS・CPU・メモリ)を一括取得する実務自動化ガイド

Tech

SYSTEM_INFO_WMI_VBA_V1_0 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

【VBA×WMI】リモートPCのシステム情報(OS・CPU・メモリ)を一括取得する実務自動化ガイド

【背景と目的】

複数端末のスペック調査を自動化し、手作業による工数を削減します。リモート接続時の「拒否」や「応答なし」による処理停止を防ぐ設計が実務上の鍵となります。

【処理フロー図】

graph TD
A["開始"] --> B["対象PC名リストの読み込み"]
B --> C["WMI接続試行"]
C --> D{"接続成功?"}
D -- Yes --> E["Win32クラスから情報抽出"]
D -- No --> F["エラー内容を記録"]
E --> G["配列へデータ格納"]
G --> H["全PC終了まで反復"]
H --> I["Excelシートへ一括出力"]
I --> J["終了"]

【実装:VBAコード】

参照設定を不要にする「レイトバインディング(遅延結合)」を採用し、配布しやすい構成にしています。

Option Explicit

' Win32 API宣言(64bit環境対応)
#If VBA7 Then

    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else

    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Sub GetRemoteSystemInfo()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.ActiveSheet

    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    ' 高速化設定
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    Dim i As Long
    Dim strComputer As String
    Dim objWMIService As Object
    Dim colItems As Object
    Dim objItem As Object
    Dim results() As Variant
    ReDim results(1 To lastRow - 1, 1 To 4) ' PC名, OS, CPU, Memory

    On Error Resume Next

    For i = 2 To lastRow
        strComputer = ws.Cells(i, 1).Value
        results(i - 1, 1) = strComputer

        If strComputer <> "" Then
            ' WMIサービスへの接続(タイムアウト考慮なしの標準接続)
            Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

            If Err.Number = 0 Then
                ' --- OS情報の取得 ---
                Set colItems = objWMIService.ExecQuery("Select Caption from Win32_OperatingSystem")
                For Each objItem In colItems
                    results(i - 1, 2) = objItem.Caption
                Next

                ' --- CPU情報の取得 ---
                Set colItems = objWMIService.ExecQuery("Select Name from Win32_Processor")
                For Each objItem In colItems
                    results(i - 1, 3) = objItem.Name
                Next

                ' --- メモリ情報の取得 (単位: GB) ---
                Set colItems = objWMIService.ExecQuery("Select TotalPhysicalMemory from Win32_ComputerSystem")
                For Each objItem In colItems
                    results(i - 1, 4) = Round(objItem.TotalPhysicalMemory / 1024 / 1024 / 1024, 2) & " GB"
                Next
            Else
                ' 接続エラー時の処理
                results(i - 1, 2) = "接続エラー: " & Err.Description
                Err.Clear
            End If
        End If

        ' オブジェクトの解放
        Set objWMIService = Nothing
        Set colItems = Nothing
    Next i

    ' 結果を一括出力
    ws.Range("B2").Resize(UBound(results, 1), UBound(results, 2)).Value = results

    ' 設定の復元
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    On Error GoTo 0

    MsgBox "情報取得が完了しました。", vbInformation
End Sub

【技術解説】

  1. WMI (Windows Management Instrumentation): Windows OSを管理するためのインターフェースです。winmgmts: モニカーを使用してリモート名前空間にアクセスします。

  2. 遅延結合 (Late Binding): CreateObjectGetObject を使用することで、実行環境に依存せず、特定のライブラリ(Microsoft WMI Scripting V1.2 Library等)への参照設定が不要になります。

  3. Win32クラスの選定:

    • Win32_OperatingSystem: OSのバージョンやエディション。

    • Win32_Processor: CPUの名称やコア数。

    • Win32_ComputerSystem: 合計物理メモリ。

  4. 配列処理の最適化: セルへの書き込みをループ内で行わず、一度配列に格納してから一括出力することで、通信負荷と描画負荷を最小限に抑えています。

【注意点と運用】

  1. ファイアウォールの遮断: リモートPC側で「Windows Management Instrumentation (WMI)」の通信が許可されていない場合、接続エラーとなります。GPO(グループポリシー)等での事前設定が推奨されます。

  2. 実行権限: リモート接続には、対象PCに対する「管理者権限」を持つユーザーでVBA(Excel)を実行している必要があります。

  3. タイムアウトの課題: GetObject はネットワーク接続不能なPCに対して数十秒フリーズする場合があります。大量のリストを処理する際は、事前に Ping 関数(Win32 API)で生存確認を行うロジックの追加を検討してください。

【まとめ】

  • 疎通確認が先決: WMI接続前にPingで対象の生存を確認し、無駄な待機時間を削減する。

  • 権限管理の徹底: 実行ユーザーが管理共有(C$等)にアクセスできる権限を有しているか確認する。

  • エラーハンドリング: 接続不可・情報欠落を想定し、On Error Resume Next を適切に制御してログを残す。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

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