はじめに (対象読者・この記事でわかること)

この記事は、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つのクラスが階層的に結びついていることを理解します。

  1. Win32_DiskDrive … 物理ディスク(\.\PHYSICALDRIVE0 など)
  2. Win32_DiskPartition … そのディスク上に存在するパーティション
  3. Win32_LogicalDisk … パーティションにフォーマットされたボリューム(C:、D: など)
  4. Win32_DiskDriveToDiskPartition / Win32_LogicalDiskToPartition … 関連付けを取るための結合クラス(アソシエーション)

要は「DiskDrive → Partition → LogicalDisk」と辿れば、物理ディスク番号からドライブレターが特定できます。
アソシエーションクラスを使うと、わざわざDeviceIDを文字列分解しなくても、PowerShellのJoin-Object(または独自のハッシュ結合)で簡単に結合できます。

ステップ2:一発で結合するワンライナーを作る

Get-CimInstanceはPowerShell 3.0以降で利用でき、WMIより高速・省メモリです。
以下を管理者権限で実行するだけで、「DiskIndex, Model, DriveLetter, Size(GB)」が一気に得られます。

Powershell
Get-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:関数化して再利用しやすくする

ワンライナーのままでは、他のスクリプトから呼び出しにくいので、関数にまとめましょう。
必要に応じて「モデル名フィルタ」「サイズ閾」「未フォーマットボリュームも表示するスイッチ」を用意すると汎用性が上がります。

Powershell
function 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クラス)を使う必要があります。

代替クエリ例:

Powershell
Get-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で取得する方法を紹介する予定です。

参考資料