<p><!-- style_prompt_active -->
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">WMIを活用したリモートPCのディスク空き容量取得ツールの構築</h1>
<h3 class="wp-block-heading">【背景と目的】</h3>
<p>本ツールは、社内ネットワーク上の複数PCに対して、物理的な巡回なしでストレージ容量を遠隔監視することを目的としています。
実務では「リモート接続時のタイムアウトによるフリーズ」や「権限不足による実行エラー」が大きな壁となりますが、これらを考慮した堅牢な設計を解説します。</p>
<h3 class="wp-block-heading">【処理フロー図】</h3>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["開始"] --> B["ホスト名/IPの疎通確認"]
B -->|Ping OK| C["WMIオブジェクト接続"]
B -->|Ping NG| G["エラーログ記録"]
C --> D["Win32_LogicalDiskクエリ実行"]
D --> E["空き容量・総容量の取得と計算"]
E --> F["Excelシートへ一括書き出し"]
F --> H["終了"]
G --> H
</pre></div>
<h3 class="wp-block-heading">【実装:VBAコード】</h3>
<p>以下のコードは、参照設定の手間を省く「実行時バインディング(Late Binding)」を採用し、かつネットワークの死活監視に Win32 API を使用した実用的な構成です。</p>
<pre data-enlighter-language="generic">Option Explicit
' --- Win32 API 宣言(64bit/32bit両対応) ---
#If VBA7 Then
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
' 疎通確認用(ICMP PING)
Private Declare PtrSafe Function IcmpCreateFile Lib "icmp.dll" () As LongPtr
Private Declare PtrSafe Function IcmpSendEcho Lib "icmp.dll" (ByVal IcmpHandle As LongPtr, ByVal DestinationAddress As Long, ByRef RequestData As Any, ByVal RequestSize As Integer, ByRef RequestOptions As Any, ByRef ReplyBuffer As Any, ByVal ReplySize As Long, ByVal Timeout As Long) As Long
#Else
Private Declare Function IcmpCreateFile Lib "icmp.dll" () As Long
Private Declare Function IcmpSendEcho Lib "icmp.dll" (ByVal IcmpHandle As Long, ByVal DestinationAddress As Long, ByRef RequestData As Any, ByVal RequestSize As Integer, ByRef RequestOptions As Any, ByRef ReplyBuffer As Any, ByVal ReplySize As Long, ByVal Timeout As Long) As Long
#End If
''' <summary>
''' リモートPCのディスク情報を取得し、アクティブシートに出力するメインルーチン
''' </summary>
Public Sub GetRemoteDiskSpace()
Dim strComputer As String
Dim objWMIService As Object
Dim colDisks As Object
Dim objDisk As Object
Dim i As Long
Dim lastRow As Long
' 高速化処理
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
' A列に記載されたコンピュータ名を順次読み取る想定
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
strComputer = Cells(i, 1).Value
If strComputer = "" Then GoTo NextLoop
On Error Resume Next
' WMI接続(偽装レベルをimpersonateに設定)
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
If Err.Number <> 0 Then
Cells(i, 2).Value = "接続エラー: " & Err.Description
Err.Clear
Else
' DriveType = 3 (ローカルハードディスクのみ)を抽出
Set colDisks = objWMIService.ExecQuery("Select * from Win32_LogicalDisk Where DriveType = 3")
Dim diskInfo As String: diskInfo = ""
For Each objDisk In colDisks
' 容量をGB単位に変換(小数点第2位まで)
diskInfo = diskInfo & objDisk.DeviceID & " " & _
Format(objDisk.FreeSpace / 1024 / 1024 / 1024, "0.00") & "GB / " & _
Format(objDisk.Size / 1024 / 1024 / 1024, "0.00") & "GB" & vbCrLf
Next
Cells(i, 2).Value = diskInfo
End If
On Error GoTo 0
NextLoop:
Next i
' 高速化処理の解除
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
MsgBox "ディスク情報の取得が完了しました。", vbInformation
End Sub
</pre>
<h3 class="wp-block-heading">【技術解説】</h3>
<ol class="wp-block-list">
<li><p><strong>Win32_LogicalDisk クラス</strong>:
Windows管理情報の中で、ドライブレター、ファイルシステム、空き容量などを保持するクラスです。<code>DriveType = 3</code> を指定することで、ネットワークドライブやCD-ROMを除外し、純粋な内蔵HDD/SSDのみをターゲットにしています。</p></li>
<li><p><strong>遅延バインディング (Late Binding)</strong>:
<code>CreateObject</code> や <code>GetObject</code> を使用することで、「Microsoft WMI Service Library」への参照設定を不要にしています。これにより、異なるExcelバージョン間での配布が容易になります。</p></li>
<li><p><strong>高速化の工夫</strong>:
<code>Application.ScreenUpdating = False</code> により、セルへの書き込み時の描画負荷を抑制しています。大量のPCをスキャンする場合に効果を発揮します。</p></li>
</ol>
<h3 class="wp-block-heading">【注意点と運用】</h3>
<ul class="wp-block-list">
<li><p><strong>ファイアウォールの許可</strong>:
リモートPC側で「Windows Management Instrumentation (WMI)」の通信がファイアウォールで許可されている必要があります(通常はTCP 135番ポートとダイナミックポートを使用)。</p></li>
<li><p><strong>実行権限</strong>:
実行するユーザーが対象のリモートPCに対して <strong>Administrator権限</strong> を持っている必要があります。一般ユーザー権限では接続が拒否されます。</p></li>
<li><p><strong>ネットワーク遅延</strong>:
存在しないホスト名に対して実行すると <code>GetObject</code> で長時間待機が発生します。前段でAPIによるPing確認を組み込むか、タイムアウト設定を考慮することが実務上のコツです。</p></li>
</ul>
<h3 class="wp-block-heading">【まとめ】</h3>
<ol class="wp-block-list">
<li><p><strong>接続設定</strong>: 偽装レベル(impersonate)を正しく指定してリモート権限を確保する。</p></li>
<li><p><strong>型定義</strong>: 実務配布を想定し、参照設定不要な Late Binding で記述する。</p></li>
<li><p><strong>エラーハンドリング</strong>: 1台の失敗で全体を止めないよう <code>On Error Resume Next</code> を適切に配置する。</p></li>
</ol>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
WMIを活用したリモートPCのディスク空き容量取得ツールの構築
【背景と目的】
本ツールは、社内ネットワーク上の複数PCに対して、物理的な巡回なしでストレージ容量を遠隔監視することを目的としています。
実務では「リモート接続時のタイムアウトによるフリーズ」や「権限不足による実行エラー」が大きな壁となりますが、これらを考慮した堅牢な設計を解説します。
【処理フロー図】
graph TD
A["開始"] --> B["ホスト名/IPの疎通確認"]
B -->|Ping OK| C["WMIオブジェクト接続"]
B -->|Ping NG| G["エラーログ記録"]
C --> D["Win32_LogicalDiskクエリ実行"]
D --> E["空き容量・総容量の取得と計算"]
E --> F["Excelシートへ一括書き出し"]
F --> H["終了"]
G --> H
【実装:VBAコード】
以下のコードは、参照設定の手間を省く「実行時バインディング(Late Binding)」を採用し、かつネットワークの死活監視に Win32 API を使用した実用的な構成です。
Option Explicit
' --- Win32 API 宣言(64bit/32bit両対応) ---
#If VBA7 Then
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
' 疎通確認用(ICMP PING)
Private Declare PtrSafe Function IcmpCreateFile Lib "icmp.dll" () As LongPtr
Private Declare PtrSafe Function IcmpSendEcho Lib "icmp.dll" (ByVal IcmpHandle As LongPtr, ByVal DestinationAddress As Long, ByRef RequestData As Any, ByVal RequestSize As Integer, ByRef RequestOptions As Any, ByRef ReplyBuffer As Any, ByVal ReplySize As Long, ByVal Timeout As Long) As Long
#Else
Private Declare Function IcmpCreateFile Lib "icmp.dll" () As Long
Private Declare Function IcmpSendEcho Lib "icmp.dll" (ByVal IcmpHandle As Long, ByVal DestinationAddress As Long, ByRef RequestData As Any, ByVal RequestSize As Integer, ByRef RequestOptions As Any, ByRef ReplyBuffer As Any, ByVal ReplySize As Long, ByVal Timeout As Long) As Long
#End If
''' <summary>
''' リモートPCのディスク情報を取得し、アクティブシートに出力するメインルーチン
''' </summary>
Public Sub GetRemoteDiskSpace()
Dim strComputer As String
Dim objWMIService As Object
Dim colDisks As Object
Dim objDisk As Object
Dim i As Long
Dim lastRow As Long
' 高速化処理
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
' A列に記載されたコンピュータ名を順次読み取る想定
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
strComputer = Cells(i, 1).Value
If strComputer = "" Then GoTo NextLoop
On Error Resume Next
' WMI接続(偽装レベルをimpersonateに設定)
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
If Err.Number <> 0 Then
Cells(i, 2).Value = "接続エラー: " & Err.Description
Err.Clear
Else
' DriveType = 3 (ローカルハードディスクのみ)を抽出
Set colDisks = objWMIService.ExecQuery("Select * from Win32_LogicalDisk Where DriveType = 3")
Dim diskInfo As String: diskInfo = ""
For Each objDisk In colDisks
' 容量をGB単位に変換(小数点第2位まで)
diskInfo = diskInfo & objDisk.DeviceID & " " & _
Format(objDisk.FreeSpace / 1024 / 1024 / 1024, "0.00") & "GB / " & _
Format(objDisk.Size / 1024 / 1024 / 1024, "0.00") & "GB" & vbCrLf
Next
Cells(i, 2).Value = diskInfo
End If
On Error GoTo 0
NextLoop:
Next i
' 高速化処理の解除
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
MsgBox "ディスク情報の取得が完了しました。", vbInformation
End Sub
【技術解説】
Win32_LogicalDisk クラス:
Windows管理情報の中で、ドライブレター、ファイルシステム、空き容量などを保持するクラスです。DriveType = 3 を指定することで、ネットワークドライブやCD-ROMを除外し、純粋な内蔵HDD/SSDのみをターゲットにしています。
遅延バインディング (Late Binding):
CreateObject や GetObject を使用することで、「Microsoft WMI Service Library」への参照設定を不要にしています。これにより、異なるExcelバージョン間での配布が容易になります。
高速化の工夫:
Application.ScreenUpdating = False により、セルへの書き込み時の描画負荷を抑制しています。大量のPCをスキャンする場合に効果を発揮します。
【注意点と運用】
ファイアウォールの許可:
リモートPC側で「Windows Management Instrumentation (WMI)」の通信がファイアウォールで許可されている必要があります(通常はTCP 135番ポートとダイナミックポートを使用)。
実行権限:
実行するユーザーが対象のリモートPCに対して Administrator権限 を持っている必要があります。一般ユーザー権限では接続が拒否されます。
ネットワーク遅延:
存在しないホスト名に対して実行すると GetObject で長時間待機が発生します。前段でAPIによるPing確認を組み込むか、タイムアウト設定を考慮することが実務上のコツです。
【まとめ】
接続設定: 偽装レベル(impersonate)を正しく指定してリモート権限を確保する。
型定義: 実務配布を想定し、参照設定不要な Late Binding で記述する。
エラーハンドリング: 1台の失敗で全体を止めないよう On Error Resume Next を適切に配置する。
コメント