本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
VBAでWMIのWin32_LogicalDiskクラスからリモートPCのディスク空き容量を照会する
【背景と目的】
複数PCのディスク容量調査を手動で行うと多大な工数がかかります。本稿では、VBAとWMI接続のタイムアウトやエラーを考慮しつつ、高速かつ一括で情報を収集する仕組みを構築します。
【処理フロー図】
graph TD A["処理開始"] --> B["画面更新・自動計算の停止"] B --> C["対象PC名のリストを走査"] C --> D["WMI接続の試行"] D -->|接続失敗| E["配列に接続エラーを記録"] D -->|接続成功| F["Win32_LogicalDisk情報のクエリ実行"] F --> G["ローカルディスク情報の抽出"] G --> H["容量変換と計算(GB単位化)"] H --> I["配列に取得結果を格納"] E --> J["次PCの処理へループ"] I --> J J -->|全PC完了| K["シートへ配列情報を一括書き出し"] K --> L["画面更新・自動計算の再開"] L --> M["処理終了"]
【実装:VBAコード】
Option Explicit
' ==============================================================================
' 処理名:GetRemoteDiskSpace
' 概要 :リモートPCの「Win32_LogicalDisk」からローカルディスク情報を取得し、
' アクティブシートに一覧出力します。
' 備考 :参照設定不要(Late Binding)、高速書き込み、エラーハンドリング実装
' ==============================================================================
Sub GetRemoteDiskSpace()
' Excel描画・自動計算の停止(処理の高速化)
On Error GoTo ErrorHandler
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With
Dim ws As Worksheet
Set ws = ActiveSheet
' A列にPC名が入力されていると仮定(2行目からスタート)
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then
MsgBox "A列の2行目以降に対象のPC名を入力してください。", vbExclamation, "確認"
GoTo CleanExit
End If
' 結果を格納する一時二次元配列(セルへの都度書き込みによる遅延を防止)
' 列構成:[PC名, ドライブ, 空き容量(GB), 総容量(GB), 使用率(%), 状態]
Dim resultData() As Variant
ReDim resultData(1 To lastRow - 1, 1 To 6)
Dim i As Long
Dim pcName As String
For i = 2 To lastRow
pcName = Trim(ws.Cells(i, 1).Value)
resultData(i - 1, 1) = pcName
If pcName = "" Then
resultData(i - 1, 6) = "PC名未入力"
GoTo NextPC
End If
' WMIオブジェクトの定義
Dim objWMIService As Object
Dim colDisks As Object
Dim objDisk As Object
Dim wmiQuery As String
' 接続エラーを個別に処理するため、一時的にエラーハンドリングを無効化
On Error Resume Next
' リモートPCのWMI namespace(CIMV2)へ接続
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & pcName & "\root\cimv2")
If Err.Number <> 0 Then
resultData(i - 1, 6) = "接続失敗 (Error: " & Err.Description & ")"
Err.Clear
On Error GoTo ErrorHandler
GoTo NextPC
End If
On Error GoTo ErrorHandler
' DriveType = 3 (ローカルハードディスクのみ)をフィルタリングするクエリ
wmiQuery = "SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3"
Set colDisks = objWMIService.ExecQuery(wmiQuery)
Dim diskInfoCount As Long
diskInfoCount = 0
' 各ディスク情報を取得(代表として最初のローカルディスク [Cドライブ等] を取得)
For Each objDisk In colDisks
Dim freeBytes As Double
Dim totalBytes As Double
' Null値(空値)による型ミスマッチの防止
freeBytes = IIf(IsNull(objDisk.FreeSpace), 0, CDbl(objDisk.FreeSpace))
totalBytes = IIf(IsNull(objDisk.Size), 0, CDbl(objDisk.Size))
resultData(i - 1, 2) = objDisk.DeviceID ' ドライブ文字 (例: "C:")
' バイトをGB(ギガバイト)に換算(1024^3 = 1,073,741,824)して小数点以下第2位で丸める
resultData(i - 1, 3) = Round(freeBytes / 1073741824, 2)
resultData(i - 1, 4) = Round(totalBytes / 1073741824, 2)
If totalBytes > 0 Then
resultData(i - 1, 5) = Round(((totalBytes - freeBytes) / totalBytes) * 100, 1) & "%"
Else
resultData(i - 1, 5) = "N/A"
End If
resultData(i - 1, 6) = "取得成功"
diskInfoCount = diskInfoCount + 1
Exit For ' 本サンプルでは簡易化のため、1つ目の代表ドライブ取得時点でループを出ます
Next objDisk
If diskInfoCount = 0 Then
resultData(i - 1, 6) = "ローカルディスク非検出"
End If
NextPC:
Next i
' 結果出力セクションのヘッダー作成
ws.Range("B1:G1").Value = Array("ドライブ", "空き容量(GB)", "総容量(GB)", "使用率", "ステータス")
' 配列からシートへ一括書き出し(処理速度向上の要)
ws.Range("B2").Resize(UBound(resultData, 1), UBound(resultData, 2)).Value = resultData
MsgBox "リモートPCのディスク容量照会が完了しました。", vbInformation, "完了"
CleanExit:
' 画面更新・自動計算の設定を復元(異常終了時も必ず通過させる)
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
Exit Sub
ErrorHandler:
MsgBox "予期せぬエラーが発生しました。" & vbCrLf & "エラー内容:" & Err.Description, vbCritical, "システムエラー"
Resume CleanExit
End Sub
【技術解説】
WMIクラス
Win32_LogicalDiskの利用 Windowsが標準搭載するWMIを利用し、特定PCのドライブ種別、全体の物理サイズ、および現在の空き容量をネットワーク越しに取得します。DriveType = 3で抽出することで、ネットワーク共有フォルダや仮想ドライブ、DVD-ROMなどを排他し、実体のあるローカルHDD/SSDのみを正確に補足します。Late Bindingによる参照設定フリー
GetObject関数を用いた遅延結合により、VBA実行環境に左右されずコードが動きます。特定のActiveXや参照ライブラリの事前登録が不要になるため、別端末への横展開が極めて容易です。二次元配列を活用した一括転記による極小負荷化 セルの値をループ内で都度書き替えるとExcelの描画処理がボトルネックとなります。データをすべてメモリ上の二次元配列(
resultData)に蓄積し、最後にRange.Resizeを使って一括展開することで、数百台規模のPCであっても一瞬でデータ書き込みが完了します。
【注意点と運用】
管理者権限の確保(最も重要) リモート接続先のWMIへ問い合わせるには、呼び出し元ユーザーが接続先のPCに対する管理者権限(Administrator権限等)を保持している必要があります。ドメイン環境下や適切なアカウントポリシーが共有されていることが前提となります。
ファイアウォール(DCOM/WMIポート)の疎通 リモートPC側で「WMI(DCOM受信)」ルールがブロックされていると、接続時にフリーズまたは「リモートサーバーが応答しません」等のエラーが返ります。
タイムアウトによるExcelのフリーズ対策 応答のない(電源が切れている)PCに対してWMI接続を行うと、タイムアウトを待つ最大数十秒間、VBAの処理全体が一時停止(応答なし)になります。これを防ぐためには、WMI接続前に
Pingのコマンドを発行し、疎通が取れたPCにのみWMI接続を試行するロジックを追加することが実務上効果的です。
【まとめ】
権限設定の確認:ドメイン管理下または双方のローカルに同一管理者パスワードが存在する環境下で実行する。
配列化による省力化:PC台数が多い時こそ、セル書き込みを最小化する配列技術が効力を発揮する。
エラー処理の分離:個々の接続障害が全体処理を止めないよう、
On Error Resume Nextを特定の行のみに限定適用して対処する。

コメント