VBAとWMIによるリモートPC情報の一括取得:運用効率化と資産管理の自動化

Tech

  • 専門用語を適切に用い、論理的かつ構造的な解説を行う。

  • Win32 APIの宣言には必ず PtrSafe を含め、64bit/32bit両対応とする。

  • コードは読みやすさと再利用性を重視し、実務的なエラーハンドリングを組み込む。

  • ユーザーの要求に忠実に従い、指示された順序で構成する。

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

VBAとWMIによるリモートPC情報の一括取得:運用効率化と資産管理の自動化

【背景と目的】

IT資産管理において、数百台のPCスペックを手作業で確認するのは非効率であり、入力ミスも避けられません。本ガイドでは、VBAからWMI(Windows Management Instrumentation)を利用し、ネットワーク経由で複数台のOS・CPU・メモリ情報を一括取得する高速なロジックを提供します。

【処理フロー図】

graph TD
A["開始"] --> B["対象PCリストのループ処理"]
B --> C["WMI接続試行"]
C --> D{"接続成否?"}
D -->|成功| E["OS・CPU・メモリ情報取得"]
D -->|失敗| F["エラー内容を配列へ格納"]
E --> G["取得データを配列へ格納"]
G --> H["全PC終了?"]
H -->|No| B
H -->|Yes| I["Excelシートへ一括書き出し"]
I --> J["終了"]

【実装:VBAコード】

Option Explicit

' 64bit環境に対応したWin32 APIの宣言(ミリ秒単位の待機用)
#If VBA7 Then

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

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

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

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

    If lastRow < 2 Then
        MsgBox "PCリストがありません。", vbExclamation
        Exit Sub
    End If

    ' 高速化のため画面更新を停止
    Application.ScreenUpdating = False

    Dim pcNames As Variant
    pcNames = ws.Range("A2:A" & lastRow).Value

    ' 結果を格納する配列 (PC名, OS, CPU, メモリ, ステータス)
    Dim results() As Variant
    ReDim results(1 To UBound(pcNames, 1), 1 To 5)

    Dim i As Long
    Dim strComputer As String
    Dim objWMI As Object
    Dim colOS As Object, colCPU As Object, colCS As Object
    Dim objItem As Object

    For i = 1 To UBound(pcNames, 1)
        strComputer = pcNames(i, 1)
        results(i, 1) = strComputer

        ' エラーハンドリング:リモートPCに接続できない場合を想定
        On Error Resume Next
        Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

        If Err.Number <> 0 Then
            results(i, 5) = "接続エラー: " & Err.Description
            Err.Clear
        Else
            ' OS情報の取得
            Set colOS = objWMI.ExecQuery("Select * from Win32_OperatingSystem")
            For Each objItem In colOS
                results(i, 2) = objItem.Caption & " (" & objItem.Version & ")"
            Next

            ' CPU情報の取得
            Set colCPU = objWMI.ExecQuery("Select * from Win32_Processor")
            For Each objItem In colCPU
                results(i, 3) = Trim(objItem.Name)
            Next

            ' 合計物理メモリの取得 (バイト単位をGBに変換)
            Set colCS = objWMI.ExecQuery("Select * from Win32_ComputerSystem")
            For Each objItem In colCS
                results(i, 4) = Round(objItem.TotalPhysicalMemory / 1024 / 1024 / 1024, 2) & " GB"
            Next

            results(i, 5) = "成功"
        End If
        On Error GoTo 0

        ' WMIリソースの解放
        Set objWMI = Nothing
    Next i

    ' シートに一括出力
    ws.Range("B2").Resize(UBound(results, 1), UBound(results, 2)).Value = results

    Application.ScreenUpdating = True
    MsgBox "情報取得が完了しました。", vbInformation
End Sub

【技術解説】

  1. Late Binding(実行時結合)の採用: CreateObjectGetObject を利用することで、特定のライブラリ(Microsoft WMI Scripting Library等)への参照設定を不要にしています。これにより、配布先での参照不可エラーを回避します。

  2. WMIクエリの活用: Win32_OperatingSystemWin32_ProcessorWin32_ComputerSystem の各クラスをSQLライクなクエリで呼び出すことで、必要なプロパティに絞った効率的なデータ抽出を行っています。

  3. 配列処理による高速化: セルへの書き込みをループ内で行わず、全てのデータを一度 Variant 配列に格納してからシートへ出力することで、Excelのオーバーヘッドを最小限に抑えています。

【注意点と運用】

  • 管理者権限とRPC接続: リモートPCから情報を取得するには、対象マシンに対する管理者権限が必要です。また、Windowsファイアウォールで「Windows Management Instrumentation (WMI)」の通信が許可されている必要があります。

  • タイムアウトの考慮: PCがオフラインの場合、GetObject でタイムアウトが発生し処理が一時停止します。本コードでは On Error Resume Next でスキップしていますが、大規模環境では事前に Ping による死活監視を行うロジックの追加を推奨します。

  • メモリ表記の誤差: TotalPhysicalMemory はハードウェアで予約された領域を除いた値を返す場合があるため、物理的な搭載容量と若干の差が出ることがあります。

【まとめ】

  1. 権限管理: 実行ユーザーが対象PCに対して管理者権限を持っていることを確認する。

  2. エラー耐性: 接続失敗を前提としたエラーハンドリングを組み込み、処理を止めない設計にする。

  3. 一括出力: セルへの書き込み回数を減らすため、必ず配列を経由して処理を高速化させる。

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

コメント

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