VBAとWMIによるリモートPC情報一括取得:IT資産管理の自動化
【背景と目的】
複数台のPCスペック調査において、手動確認の手間やWMI接続の遅延によるExcelのフリーズ、権限不足によるエラーを、非同期接続と配列処理で解決します。
【処理フロー図】
graph TD
A["開始"] --> B["PC名リストの読み込み"]
B --> C["画面更新の停止/配列の初期化"]
C --> D{"リモートWMI接続試行"}
D -- 接続成功 --> E["OS/CPU/メモリ情報のクエリ実行"]
D -- タイムアウト/拒否 --> F["エラー情報を配列に格納"]
E --> G["取得データを配列へ格納"]
G --> H{"次のPCがあるか?"}
F --> H
H -- Yes --> D
H -- No --> I["Excelシートへ一括書き出し"]
I --> J["画面更新の再開/終了"]
【実装:VBAコード】
Option Explicit
' --- Win32 API 宣言 (実行時間計測用) ---
#If VBA7 Then
Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else
Private Declare Function GetTickCount Lib "kernel32" () As Long
#End If
' -----------------------------------------------------------------------------
' 概要: 指定されたPCリストからシステム情報を取得する
' 備考: 参照設定不要 (Late Binding)
' -----------------------------------------------------------------------------
Public Sub GetRemoteSystemInfo()
Dim ws As Worksheet: Set ws = ThisWorkbook.ActiveSheet
Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then Exit Sub
Dim pcList As Variant: pcList = ws.Range("A2:A" & lastRow).Value
Dim results() As Variant
ReDim results(1 To UBound(pcList, 1), 1 To 4) ' OS, CPU, RAM, Status
Dim i As Long
Dim strPC As String
Dim objWMIService As Object
Dim colItems As Object
Dim objItem As Object
Dim startTime As Long
' 高速化設定
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
On Error Resume Next
For i = 1 To UBound(pcList, 1)
strPC = Trim(pcList(i, 1))
results(i, 4) = "Pending"
If strPC <> "" Then
' WMIロケーター経由で接続
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strPC & "\root\cimv2")
If Err.Number <> 0 Then
results(i, 4) = "Error: " & Err.Description
Err.Clear
Else
' 1. OS情報の取得
Set colItems = objWMIService.ExecQuery("Select Caption from Win32_OperatingSystem")
For Each objItem In colItems
results(i, 1) = objItem.Caption
Next
' 2. CPU情報の取得
Set colItems = objWMIService.ExecQuery("Select Name from Win32_Processor")
For Each objItem In colItems
results(i, 2) = objItem.Name
Next
' 3. メモリ情報の取得 (GB換算)
Set colItems = objWMIService.ExecQuery("Select TotalPhysicalMemory from Win32_ComputerSystem")
For Each objItem In colItems
results(i, 3) = Round(objItem.TotalPhysicalMemory / 1024 / 1024 / 1024, 2) & " GB"
Next
results(i, 4) = "Success"
End If
End If
Set objWMIService = Nothing
Next i
On Error GoTo 0
' 結果を一括出力 (B列~E列)
ws.Range("B2").Resize(UBound(results, 1), UBound(results, 2)).Value = results
' 設定の復元
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "情報取得が完了しました。", vbInformation
End Sub
【技術解説】
Late Bindingの採用:
GetObjectを使用することで、配布先PCのExcel環境における「Microsoft WMI Scripting V1.2 Library」への参照設定の有無に依存せず動作させます。配列一括処理: 1セルずつ書き込むのではなく、
results配列にデータを蓄積し、最後にRange.Value = resultsで一括出力することで、通信以外の処理オーバーヘッドを極小化しています。WMI クラスの選定:
Win32_OperatingSystem: OS名取得用。Win32_Processor: プロセッサ名取得用。Win32_ComputerSystem: 物理メモリの合計値取得用(Win32_PhysicalMemoryよりもシンプルに合計値が得られます)。
【注意点と運用】
ファイアウォールの遮断: リモートPC側で「Windows Management Instrumentation (WMI)」の受信ルールが許可されていない場合、接続エラー(0x800706BA等)が発生します。
実行権限: 実行ユーザーには対象PCに対する管理者権限(Administrator権限)が必要です。ドメイン環境での実行を推奨します。
タイムアウトの課題: 存在しないPC名に対して
GetObjectを実行すると、数十秒応答がなくなる場合があります。リストの事前クリーニング(Ping確認等)との併用が効果的です。
【まとめ】
権限の確認: 実行前にドメイン管理者権限または対象PCのローカル管理者権限があるか確認すること。
配列の活用: セルへの書き込み回数を減らし、実行速度の低下とExcelのフリーズを防止すること。
エラー処理の徹底:
On Error Resume Nextを接続試行部で適切に使い、特定PCの失敗でマクロ全体が止まらないように設計すること。

