はじめに (対象読者・この記事でわかること)
この記事は、Windowsサーバーの運用・インフラエンジニアや、PowerShellでシステム情報を取得したい中級者以上の方を対象としています。
「デバイスマネージャーでディスク0と表示されているハードウェアが、実際にC:かD:のどちらに割り当たっているのか」を、GUIではなくスクリプトで瞬時に特定したい方に最適です。
この記事を読むことで、WMIクラス(Win32_DiskDrive、Win32_DiskPartition、Win32_LogicalDiskなど)の関連性が分かり、物理ディスク番号からドライブレターを逆引きするワンライナーおよび再利用可能な関数の作り方が身につきます。
また、Get-WmiObjectではなくGet-CimInstanceを使った最新の記法に対応できるため、古いOSから最新のWindows 11/Server 2025まで同じスクリプトで動作させることができます。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- PowerShellの基本的なパイプラインとフィルタ(Where-Object、Select-Object)
- WMI/CIMの概念と、Get-WmiObject/Get-CimInstanceの違いをある程度理解していること
- ディスク→パーティション→論理ドライブという階層構造をイメージできること
なぜ「物理ディスク→ドライブレター」の対応をPowerShellで知りたいのか
Windowsのデバイスマネージャーでは「ディスク0」「ディスク1」としか表示されず、それがC:、D:、E:のどれに対応するか一目では分かりません。
特に以下の場面で困りがちです。
- サーバーがランニング中に「ディスク1の異常」をアラートされ、すぐに該当するドライブレターを特定したい
- テープやUSBを増設した際、新たに割り当てられたドライブレターをスクリプトで自動取得し、バックアップバッチに渡したい
- 仮想環境でディスクを増設したとき、ゲストOS内で「どのドライブが追加されたか」を無人で特定したい
GUIで「ディスクの管理」を開けば分かりますが、リモート先のコアサーバーではGUIが使えません。
そこで、PowerShellで「物理ディスク番号→ドライブレター」のマッピングを一発で取得する方法を身につけましょう。
ステップ1:WMI/CIMクラスの関連性を理解する
まず、次の4つのクラスが階層的に結びついていることを理解します。
- Win32_DiskDrive … 物理ディスク(\.\PHYSICALDRIVE0 など)
- Win32_DiskPartition … そのディスク上に存在するパーティション
- Win32_LogicalDisk … パーティションにフォーマットされたボリューム(C:、D: など)
- Win32_DiskDriveToDiskPartition / Win32_LogicalDiskToPartition … 関連付けを取るための結合クラス(アソシエーション)
要は「DiskDrive → Partition → LogicalDisk」と辿れば、物理ディスク番号からドライブレターが特定できます。
アソシエーションクラスを使うと、わざわざDeviceIDを文字列分解しなくても、PowerShellのJoin-Object(または独自のハッシュ結合)で簡単に結合できます。
ステップ2:一発で結合するワンライナーを作る
Get-CimInstanceはPowerShell 3.0以降で利用でき、WMIより高速・省メモリです。
以下を管理者権限で実行するだけで、「DiskIndex, Model, DriveLetter, Size(GB)」が一気に得られます。
PowershellGet-CimInstance Win32_DiskDrive | ForEach-Object { $disk = $_ $partQuery = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($disk.DeviceID.Replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition" Get-CimInstance -Query $partQuery | ForEach-Object { $part = $_ $volQuery = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($part.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition" Get-CimInstance -Query $volQuery | Select-Object @{N='DiskIndex';E={$disk.Index}}, @{N='Model';E={$disk.Model}}, @{N='DriveLetter';E={$_.DeviceID}}, @{N='SizeGB';E={[math]::Round($_.Size/1GB,2)}} } } | Format-Table -AutoSize
実行結果例:
DiskIndex Model DriveLetter SizeGB
--------- ----- ----------- ------
0 SAMSUNG SSD 980 PRO 500GB C: 465.75
1 WD Red 4TB D: 3726.02
2 USB SanDisk Extreme E: 57.83
これで「ディスク0=C:」「ディスク1=D:」といった対応が即座に分かります。
管理者権限がなくても実行可能ですが、一部アタッチされていないボリュームは表示されない点に注意してください。
ステップ3:関数化して再利用しやすくする
ワンライナーのままでは、他のスクリプトから呼び出しにくいので、関数にまとめましょう。
必要に応じて「モデル名フィルタ」「サイズ閾」「未フォーマットボリュームも表示するスイッチ」を用意すると汎用性が上がります。
Powershellfunction Get-PhysicalDiskToDriveLetter { [CmdletBinding()] param( [string]$ModelLike, [uint32]$LargerThanGB, [switch]$IncludeUnformatted ) $diskList = Get-CimInstance Win32_DiskDrive if ($ModelLike) { $diskList = $diskList | Where-Object Model -like $ModelLike } foreach ($disk in $diskList) { $partQuery = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($disk.DeviceID.Replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition" $partList = Get-CimInstance -Query $partQuery foreach ($part in $partList) { $volQuery = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($part.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition" $volList = Get-CimInstance -Query $volQuery if (-not $IncludeUnformatted -and -not $volList) { continue } foreach ($vol in $volList) { if ($LargerThanGB -and ($vol.Size/1GB) -lt $LargerThanGB) { continue } [pscustomobject]@{ DiskIndex = $disk.Index Model = $disk.Model DriveLetter = $vol.DeviceID SizeGB = [math]::Round($vol.Size/1GB,2) PartitionType = $part.Type } } } } }
使い方:
Powershell# SSDのみ表示 Get-PhysicalDiskToDriveLetter -ModelLike "*SSD*" # 1TB以上のボリュームのみ Get-PhysicalDiskToDriveLetter -LargerThanGB 1024 # フォーマットされていないパーティションも含める Get-PhysicalDiskToDriveLetter -IncludeUnformatted
ハマった点と解決策
ハマりポイント1:DeviceIDのバックスラッシュがQueryでエスケープされる
ASSOCIATORS OF クエリ内でバックスラッシュがエスケープされないと、「Invalid query」例外が発生します。
$disk.DeviceID.Replace('\','\\')で二重エスケープしてやる必要があります。
ハマりポイント2:USBメモリが複数回挿抜されるとIndexが変わる
物理ディスクのIndexは起動ごとに変わる可能性があります。
継続的に同一デバイスを追跡したい場合は、SerialNumberやPNPDeviceIDをキーにした方が安定します。
ハマりポイント3:動的ディスクや論理ボリュームマネージャー(LDM)で論理ディスクが紐付かない
WindowsソフトウェアRAIDやStorage Spacesを使っていると、Win32_DiskPartitionが存在しない場合があります。
その場合はMSFT_Disk、MSFT_Volume(Storageマネジメント用CIMクラス)を使う必要があります。
代替クエリ例:
PowershellGet-CimInstance -Namespace root/microsoft/windows/storage MSFT_Disk | Get-CimAssociatedInstance -ResultClassName MSFT_Volume | Select-Object @{N='DiskNumber';E={$_.DiskNumber}}, DriveLetter, SizeGB
まとめ
本記事では、WMI/CIMクラスを活用して「物理ディスク番号→ドライブレター」の対応をPowerShellで瞬時に取得する方法を解説しました。
- Win32_DiskDrive、Win32_DiskPartition、Win32_LogicalDiskをASSOCIATORSクエリで結合することで、ワンライナーで実現できる
- Get-CimInstanceを使うことで、WMIより高速かつファイアウォール越しでも通信しやすい
- 関数化してフィルタや未フォーマットボリューム表示スイッチを付けることで、運用スクリプトへ組み込みやすくなる
このスクリプトをバッチや監視ツールに組み込めば、リモートサーバーのディスク障害アラートから該当ドライブレターを即特定できるため、ダウンタイムを最小限に抑えられます。
次回は、「Storage SpacesやリFSでの仮想ディスク」と「論理ボリューマッピング」をPowerShellで取得する方法を紹介する予定です。
参考資料
- Win32_DiskDrive class - Microsoft Learn
- Win32_DiskPartition class - Microsoft Learn
- Win32_LogicalDisk class - Microsoft Learn
- Get-CimInstance - Microsoft Learn
- Windows Storage Management API Overview - Microsoft Learn
