。 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
参照設定不要!VBAとWMIでPCのOS/ハードウェア情報を瞬時に取得する高速テクニック
【背景と目的】
VBAでPCのハードウェア情報を取得する際、参照設定(外部ライブラリ)の管理が煩雑であったり、環境依存のエラーで処理が停止したりする課題に直面します。
本手法は、Windows標準機能であるWMI(Windows Management Instrumentation)をVBAの遅延バインディング機能(CreateObject / GetObject)経由で利用することにより、外部ライブラリへの依存をゼロにし、堅牢かつ高速なシステム情報収集を実現します。
【処理フロー図】
WMIサービスに接続し、複数クラスの情報をクエリで取得し、Excelシートに出力するフローです。
graph TD
A["開始: ScreenUpdating無効化"] --> B{"WMIサービス接続"};
B --> C["ExecQuery: OS情報取得 (Win32_OperatingSystem)"];
C --> D["ExecQuery: ハードウェア情報取得 (Win32_ComputerSystem)"];
D --> E["結果をシートに書き込み"];
E --> F["終了: オブジェクト解放と高速化設定の復元"];
【実装:VBAコード】
以下のコードは、実行しているPCのOS名、バージョン、メモリ総容量などの重要情報を、参照設定なしで取得し、アクティブシートに出力します。
' // -------------------------------------------------------------------------
' // Module: 標準モジュール
' // 目的: 参照設定なしでWMI経由のシステム情報取得を行う
' // -------------------------------------------------------------------------
Sub GetSystemHardwareInfo_WMI()
' WMIオブジェクト関連
Dim objWMIService As Object
Dim colItems As Object
Dim objItem As Object
' Excel操作関連
Dim ws As Worksheet
Dim lngRow As Long
' 高速化のための設定
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set ws = ThisWorkbook.Sheets(1) ' 結果を出力するシートを指定
lngRow = 1 ' 書き出し開始行
On Error GoTo ErrorHandler
' 1. WMIサービスへの接続 (遅延バインディングで参照設定不要)
' ローカルPCのCIMV2名前空間に接続
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
If objWMIService Is Nothing Then
MsgBox "WMIサービスへの接続に失敗しました。", vbCritical
GoTo Finalize
End If
' ヘッダーの書き出し
ws.Cells(lngRow, 1).Value = "項目"
ws.Cells(lngRow, 2).Value = "値"
lngRow = lngRow + 1
' ==========================================================
' 2. OS情報の取得 (Win32_OperatingSystem)
' ==========================================================
' OS名、バージョン、アーキテクチャを取得
Set colItems = objWMIService.ExecQuery("SELECT Caption, Version, OSArchitecture, CSDVersion FROM Win32_OperatingSystem", "WQL", 48)
For Each objItem In colItems
ws.Cells(lngRow, 1).Value = "OS名"
ws.Cells(lngRow, 2).Value = objItem.Caption
lngRow = lngRow + 1
ws.Cells(lngRow, 1).Value = "OSバージョン"
ws.Cells(lngRow, 2).Value = objItem.Version
lngRow = lngRow + 1
ws.Cells(lngRow, 1).Value = "OSアーキテクチャ"
ws.Cells(lngRow, 2).Value = objItem.OSArchitecture
lngRow = lngRow + 1
ws.Cells(lngRow, 1).Value = "サービスパック"
ws.Cells(lngRow, 2).Value = objItem.CSDVersion
lngRow = lngRow + 1
Next
Set colItems = Nothing ' オブジェクトの解放
' ==========================================================
' 3. ハードウェア情報の取得 (Win32_ComputerSystem)
' ==========================================================
' PC名と物理メモリ総容量を取得
Set colItems = objWMIService.ExecQuery("SELECT Name, TotalPhysicalMemory FROM Win32_ComputerSystem", "WQL", 48)
For Each objItem In colItems
ws.Cells(lngRow, 1).Value = "PC名 (HostName)"
ws.Cells(lngRow, 2).Value = objItem.Name
lngRow = lngRow + 1
' メモリ総容量 (バイト単位で取得されるためGBに変換)
Dim dblMemoryGB As Double
' 1 GB = 1024 * 1024 * 1024 バイト
dblMemoryGB = CDbl(objItem.TotalPhysicalMemory) / (1024 ^ 3)
ws.Cells(lngRow, 1).Value = "物理メモリ総容量"
ws.Cells(lngRow, 2).Value = Format(dblMemoryGB, "0.00") & " GB"
lngRow = lngRow + 1
Next
Set colItems = Nothing
' ==========================================================
' 4. CPU情報の取得 (Win32_Processor)
' ==========================================================
Set colItems = objWMIService.ExecQuery("SELECT Name, NumberOfCores, NumberOfLogicalProcessors FROM Win32_Processor", "WQL", 48)
For Each objItem In colItems
ws.Cells(lngRow, 1).Value = "CPUモデル名"
ws.Cells(lngRow, 2).Value = objItem.Name
lngRow = lngRow + 1
ws.Cells(lngRow, 1).Value = "コア数"
ws.Cells(lngRow, 2).Value = objItem.NumberOfCores
lngRow = lngRow + 1
ws.Cells(lngRow, 1).Value = "論理プロセッサ数"
ws.Cells(lngRow, 2).Value = objItem.NumberOfLogicalProcessors
lngRow = lngRow + 1
Next
ws.Columns("A:B").AutoFit ' 列幅の自動調整
GoTo Finalize
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
Finalize:
' 使用したオブジェクトを確実に解放
Set objWMIService = Nothing
Set objItem = Nothing
Set colItems = Nothing
Set ws = Nothing
' 高速化設定の復元
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
【技術解説】
1. WMIと遅延バインディング
WMI(Windows Management Instrumentation)は、Windowsシステム全体のリソースや設定情報を標準化された方法(CIMスキーマ)で管理するための技術です。
VBAでWMIを利用する最大の利点は、遅延バインディング(GetObject や CreateObject)を利用できる点にあります。これにより、事前に「Microsoft WMI Scripting Library」を参照設定する必要がなくなります。
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
このコードは、ローカルPCのWMIサービス(winmgmts)の標準名前空間(\root\cimv2)に接続する処理を一発で行っています。参照設定不要のため、PC環境によらず実行可能なコードとなります。
2. WQL (WMI Query Language)
WMIからの情報取得は、データベースにおけるSQLに似たWQLというクエリ言語で行います。
"SELECT Caption, Version FROM Win32_OperatingSystem"
これは、「Win32_OperatingSystem クラスから Caption と Version プロパティを選択せよ」という意味です。必要な情報だけをピンポイントで取得することで、処理負荷を最小限に抑えています。
3. データ型の変換と高速化
WMIから取得されるメモリ情報(TotalPhysicalMemory)などは通常バイト単位で格納されており、VBA側で正確な表示のためにデータ型を Double にキャストし、適切な単位(GB)に変換しています。
また、コード冒頭と末尾で実行している
Application.ScreenUpdating = False Application.Calculation = xlCalculationManual
は、画面描画と再計算を停止し、VBAの実行速度を劇的に向上させるための標準的な高速化テクニックです。
【注意点と運用】
1. WMI接続エラーとその回避策
WMIは権限やサービスの状態に依存するため、接続エラーが発生する場合があります。
最も一般的なのは、リモートPCの情報を取得しようとした際に発生するアクセス拒否エラーです。ローカルPC(\\.\)の情報取得であっても、ファイアウォールやセキュリティポリシーが厳格な環境ではエラーとなる可能性があります。
回避策: 厳密なエラーハンドリング(On Error GoTo ErrorHandler)を導入し、特にGetObject実行後のオブジェクトの有効性を必ずチェックすることが重要です。
2. オブジェクトの確実な解放
WMIオブジェクト(objWMIService, colItems, objItem)はCOMオブジェクトであり、使用後には必ずメモリから解放する必要があります。これを怠ると、VBAセッション中にメモリリークが発生し、処理が不安定になる原因となります。
Set objWMIService = Nothing ' ... 他のオブジェクトも同様に解放
この処理は、エラー発生時(ErrorHandler)と正常終了時(Finalize)の双方で実行されるよう、コードのジャンプ構造を設計してください。
【まとめ】
VBAとWMIを組み合わせたシステム情報取得は、外部依存性を排し、堅牢な運用を実現します。
参照設定レスの実現:
GetObjectによる遅延バインディングを利用することで、環境依存の問題を回避し、配布しやすいコード基盤を確立できます。必要な情報のみ取得: WQLを利用して、大量のプロパティから必要なデータだけを抽出することで、処理速度を維持し、コードの可読性を高めます。
高速化と堅牢性の両立: VBAの高速化設定(
ScreenUpdating = False)と、WMIオブジェクトの厳格なエラー処理・解放を徹底することで、業務利用に耐えうる堅牢なマクロを構築できます。

