VBAとWMIで実現する「リモートPC情報一括取得システム」の構築

Tech

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

VBAとWMIで実現する「リモートPC情報一括取得システム」の構築

【背景と目的】

IT資産管理や保守にて、複数端末の情報を手動収集する負荷を解消。VBAとWMIで、OS・CPU・メモリ情報を一括取得・自動集計する仕組みを提案します。

【処理フロー図】

graph TD
A["開始"] --> B["ターゲットPCリスト読み込み"]
B --> C["リモートWMI接続試行"]
C -->|成功| D["OS/CPU/RAM情報をクエリ"]
C -->|失敗| E["エラー内容をログ出力"]
D --> F["配列に結果を格納"]
F --> G["ワークシートへ一括書き出し"]
G --> H["終了"]

【実装:VBAコード】

Option Explicit

' Win32 APIを使用する場合のPtrSafe宣言(本コードではWMIをLate Bindingで使用)
#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

''' <summary>
''' リモートPCの情報を取得し、アクティブシートに出力する
''' </summary>
Public Sub GetRemoteSystemInfo()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.ActiveSheet

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

    ' 処理高速化の設定
    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With

    Dim pcName As String
    Dim i As Long
    Dim results() As Variant
    ReDim results(1 To lastRow - 1, 1 To 4) ' OS, CPU, RAM, Status

    On Error Resume Next

    For i = 2 To lastRow
        pcName = ws.Cells(i, 1).Value
        If pcName <> "" Then
            ' 情報取得処理
            Call FetchWmiData(pcName, results, i - 1)
        End If
    Next i

    ' シートへ一括出力(セルへの個別書き込みを避けて高速化)
    ws.Range("B2").Resize(UBound(results, 1), 4).Value = results

    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
    End With

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

''' <summary>
''' WMIクエリを実行してシステム情報を配列に格納
''' </summary>
Private Sub FetchWmiData(ByVal pcName As String, ByRef results() As Variant, ByVal idx As Long)
    Dim objWMIService As Object
    Dim colItems As Object
    Dim objItem As Object
    Dim connectionPath As String

    ' リモート接続パスの構築(名前解決ができる前提)
    connectionPath = "winmgmts:{impersonationLevel=impersonate}!\\" & pcName & "\root\cimv2"

    Set objWMIService = GetObject(connectionPath)

    If Err.Number <> 0 Then
        results(idx, 4) = "接続エラー: " & Err.Description
        Err.Clear
        Exit Sub
    End If

    ' 1. OS情報の取得
    Set colItems = objWMIService.ExecQuery("Select Caption From Win32_OperatingSystem")
    For Each objItem In colItems
        results(idx, 1) = objItem.Caption
    Next

    ' 2. CPU情報の取得
    Set colItems = objWMIService.ExecQuery("Select Name From Win32_Processor")
    For Each objItem In colItems
        results(idx, 2) = objItem.Name
    Next

    ' 3. メモリ情報の取得 (単位: GBに変換)
    Set colItems = objWMIService.ExecQuery("Select TotalPhysicalMemory From Win32_ComputerSystem")
    For Each objItem In colItems
        results(idx, 3) = Round(objItem.TotalPhysicalMemory / 1024 / 1024 / 1024, 2) & " GB"
    Next

    results(idx, 4) = "成功"
End Sub

【技術解説】

  1. Late Binding (遅延結合): 参照設定(Microsoft WMI Scripting Library)を不要にするため、CreateObjectGetObjectを使用。配布時の環境差異による「参照不可」エラーを防止します。

  2. WQL (WMI Query Language): Select * From... 形式でSQLのようにOS内部情報を取得。Win32_OperatingSystem(OS名)、Win32_Processor(CPU名)、Win32_ComputerSystem(物理メモリ)を利用しています。

  3. 高速化ロジック: セルへの書き込みをループ内で行わず、一度配列(results)に格納してから Resize メソッドで一括出力。100台規模の処理でもオーバーヘッドを最小化します。

【注意点と運用】

  • 管理者権限とファイアウォール: リモートPC側で「WMIの許可」および「RPC通信(TCP 135番等)」が許可されている必要があります。ドメイン環境でない場合、接続が拒否されるケースが多いです。

  • タイムアウト: 存在しないPC名やオフラインの端末に対しては、GetObject で数十秒フリーズする場合があります。事前に Ping コマンド等で死活確認を行うロジックの追加を推奨します。

  • UACの影響: ローカル管理者権限を持つユーザーでExcelを実行する必要があります。

【まとめ】

  • 権限の確認: 実行ユーザーが対象PCの管理者権限を持っていることが大前提です。

  • 配列の活用: セル操作を最小限に抑えることで、大量端末の処理速度を劇的に向上させます。

  • エラー処理の徹底: 接続失敗を想定し、On Error Resume Next とステータスログ出力をセットで運用しましょう。

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

コメント

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