<p><system_expert_metadata_version_20241031_001_by_gemini_vba_wmi_remote_info>
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</system_expert_metadata_version_20241031_001_by_gemini_vba_wmi_remote_info></p>
<h1 class="wp-block-heading">VBAとWMIによるリモートPC情報一括取得:IT資産管理の自動化</h1>
<h3 class="wp-block-heading">【背景と目的】</h3>
<p>複数台のPCスペック調査において、手動確認の手間やWMI接続の遅延によるExcelのフリーズ、権限不足によるエラーを、非同期接続と配列処理で解決します。</p>
<h3 class="wp-block-heading">【処理フロー図】</h3>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
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["画面更新の再開/終了"]
</pre></div>
<h3 class="wp-block-heading">【実装:VBAコード】</h3>
<pre data-enlighter-language="generic">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
</pre>
<h3 class="wp-block-heading">【技術解説】</h3>
<ol class="wp-block-list">
<li><p><strong>Late Bindingの採用</strong>: <code>GetObject</code> を使用することで、配布先PCのExcel環境における「Microsoft WMI Scripting V1.2 Library」への参照設定の有無に依存せず動作させます。</p></li>
<li><p><strong>配列一括処理</strong>: 1セルずつ書き込むのではなく、<code>results</code> 配列にデータを蓄積し、最後に <code>Range.Value = results</code> で一括出力することで、通信以外の処理オーバーヘッドを極小化しています。</p></li>
<li><p><strong>WMI クラスの選定</strong>: </p>
<ul>
<li><p><code>Win32_OperatingSystem</code>: OS名取得用。</p></li>
<li><p><code>Win32_Processor</code>: プロセッサ名取得用。</p></li>
<li><p><code>Win32_ComputerSystem</code>: 物理メモリの合計値取得用(<code>Win32_PhysicalMemory</code> よりもシンプルに合計値が得られます)。</p></li>
</ul></li>
</ol>
<h3 class="wp-block-heading">【注意点と運用】</h3>
<ol class="wp-block-list">
<li><p><strong>ファイアウォールの遮断</strong>: リモートPC側で「Windows Management Instrumentation (WMI)」の受信ルールが許可されていない場合、接続エラー(0x800706BA等)が発生します。</p></li>
<li><p><strong>実行権限</strong>: 実行ユーザーには対象PCに対する管理者権限(Administrator権限)が必要です。ドメイン環境での実行を推奨します。</p></li>
<li><p><strong>タイムアウトの課題</strong>: 存在しないPC名に対して <code>GetObject</code> を実行すると、数十秒応答がなくなる場合があります。リストの事前クリーニング(Ping確認等)との併用が効果的です。</p></li>
</ol>
<h3 class="wp-block-heading">【まとめ】</h3>
<ul class="wp-block-list">
<li><p><strong>権限の確認</strong>: 実行前にドメイン管理者権限または対象PCのローカル管理者権限があるか確認すること。</p></li>
<li><p><strong>配列の活用</strong>: セルへの書き込み回数を減らし、実行速度の低下とExcelのフリーズを防止すること。</p></li>
<li><p><strong>エラー処理の徹底</strong>: <code>On Error Resume Next</code> を接続試行部で適切に使い、特定PCの失敗でマクロ全体が止まらないように設計すること。</p></li>
</ul>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
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の失敗でマクロ全体が止まらないように設計すること。
コメント