参照設定不要!VBAとWMIでPCのOS/ハードウェア情報を瞬時に取得する高速テクニック

Tech

。 本記事は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を利用する最大の利点は、遅延バインディングGetObjectCreateObject)を利用できる点にあります。これにより、事前に「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 クラスから CaptionVersion プロパティを選択せよ」という意味です。必要な情報だけをピンポイントで取得することで、処理負荷を最小限に抑えています。

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を組み合わせたシステム情報取得は、外部依存性を排し、堅牢な運用を実現します。

  1. 参照設定レスの実現: GetObjectによる遅延バインディングを利用することで、環境依存の問題を回避し、配布しやすいコード基盤を確立できます。

  2. 必要な情報のみ取得: WQLを利用して、大量のプロパティから必要なデータだけを抽出することで、処理速度を維持し、コードの可読性を高めます。

  3. 高速化と堅牢性の両立: VBAの高速化設定(ScreenUpdating = False)と、WMIオブジェクトの厳格なエラー処理・解放を徹底することで、業務利用に耐えうる堅牢なマクロを構築できます。

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

コメント

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