private/Get-OSDeployDisk.ps1

function Get-OSDeployDisk {
    <#
    .SYNOPSIS
        Gets online physical disks from the Windows Storage provider
 
    .DESCRIPTION
        Queries MSFT_Disk and MSFT_PhysicalDisk through a local CIM session, excludes
        offline disks and devices with no media, and enriches each disk with MediaType and
        SizeGB properties. Optional parameters filter the results. Provider failures write
        a nonterminating error and return no disk objects.
 
    .PARAMETER Number
        Filters by disk number. The aliases are Disk and DiskNumber. This filter is applied
        whenever the parameter is explicitly bound, including when its value is zero.
 
    .PARAMETER BootFromDisk
        Filters by the BootFromDisk Boolean property when explicitly bound.
 
    .PARAMETER IsBoot
        Filters by the IsBoot Boolean property when explicitly bound.
 
    .PARAMETER IsReadOnly
        Filters by the IsReadOnly Boolean property when explicitly bound.
 
    .PARAMETER IsSystem
        Filters by the IsSystem Boolean property when explicitly bound.
 
    .PARAMETER BusType
        Includes disks whose BusType is one of the supplied validated Windows Storage bus
        type names.
 
    .PARAMETER BusTypeNot
        Excludes disks whose BusType is one of the supplied validated Windows Storage bus
        type names.
 
    .PARAMETER MediaType
        Includes disks whose enriched MediaType is SSD, HDD, SCM, or Unspecified.
 
    .PARAMETER MediaTypeNot
        Excludes disks whose enriched MediaType is SSD, HDD, SCM, or Unspecified.
 
    .PARAMETER PartitionStyle
        Includes disks whose PartitionStyle is GPT, MBR, or RAW.
 
    .PARAMETER PartitionStyleNot
        Excludes disks whose PartitionStyle is GPT, MBR, or RAW.
 
    .EXAMPLE
        PS> Get-OSDeployDisk -BusType 'USB' -IsReadOnly $false
 
        Returns online USB disks that are not read-only.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        Microsoft.Management.Infrastructure.CimInstance. Returns zero or more MSFT_Disk
        instances enriched with MediaType and SizeGB note properties.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Dependencies:
          PowerShell Modules: Storage
          Windows Features: Windows Storage Management provider
          DotNet Classes: Microsoft.Management.Infrastructure.CimInstance,
                          Microsoft.Management.Infrastructure.CimSession
    #>

    [CmdletBinding()]
    [OutputType([Microsoft.Management.Infrastructure.CimInstance])]
    param (
        [Alias('Disk','DiskNumber')]
        [uint32]$Number,

        [bool]$BootFromDisk,
        [bool]$IsBoot,
        [bool]$IsReadOnly,
        [bool]$IsSystem,

        [ValidateSet('1394','ATA','ATAPI','Fibre Channel','File Backed Virtual','iSCSI','MMC','MAX','Microsoft Reserved','NVMe','RAID','SAS','SATA','SCSI','SD','SSA','Storage Spaces','USB','Virtual')]
        [string[]]$BusType,
        [ValidateSet('1394','ATA','ATAPI','Fibre Channel','File Backed Virtual','iSCSI','MMC','MAX','Microsoft Reserved','NVMe','RAID','SAS','SATA','SCSI','SD','SSA','Storage Spaces','USB','Virtual')]
        [string[]]$BusTypeNot,

        [ValidateSet('SSD','HDD','SCM','Unspecified')]
        [string[]]$MediaType,
        [ValidateSet('SSD','HDD','SCM','Unspecified')]
        [string[]]$MediaTypeNot,

        [ValidateSet('GPT','MBR','RAW')]
        [string[]]$PartitionStyle,
        [ValidateSet('GPT','MBR','RAW')]
        [string[]]$PartitionStyleNot
    )

    $StorageNamespace = 'ROOT/Microsoft/Windows/Storage'
    $CimSession = $null

    try {
        # Storage supplies the MSFT_Disk type data used by downstream Storage cmdlets; enumeration below uses the .NET CIM API.
        Import-Module Storage -ErrorAction Stop

        $CimSession = [Microsoft.Management.Infrastructure.CimSession]::Create($env:COMPUTERNAME)
        $GetDisk = @($CimSession.QueryInstances($StorageNamespace, 'WQL', 'SELECT * FROM MSFT_Disk')) | Sort-Object Number
        $GetPhysicalDisk = @($CimSession.QueryInstances($StorageNamespace, 'WQL', 'SELECT * FROM MSFT_PhysicalDisk')) | Sort-Object DeviceId
    }
    catch {
        Write-Error -Message "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Unable to enumerate disks by using the Storage CIM provider. $($_.Exception.Message)" -ErrorAction Continue
        return
    }
    finally {
        if ($null -ne $CimSession) {
            $CimSession.Dispose()
        }
    }

    $PhysicalDiskByDeviceId = @{}
    foreach ($PhysicalDisk in $GetPhysicalDisk) {
        $PhysicalDiskByDeviceId[[string]$PhysicalDisk.DeviceId] = $PhysicalDisk
    }

    foreach ($Disk in $GetDisk) {
        # MSFT_Disk does not expose reliable media type on every device, so preserve the existing DeviceId-to-Number enrichment.
        if ($PhysicalDiskByDeviceId.ContainsKey([string]$Disk.Number)) {
            $Disk | Add-Member -NotePropertyName 'MediaType' -NotePropertyValue $PhysicalDiskByDeviceId[[string]$Disk.Number].MediaType -Force
        }

        $Disk | Add-Member -NotePropertyName 'SizeGB' -NotePropertyValue ([int]($Disk.Size / 1GB)) -Force
    }

    $GetDisk = $GetDisk | Where-Object {$_.IsOffline -eq $false}
    $GetDisk = $GetDisk | Where-Object {$_.OperationalStatus -ne 'No Media'}

    if ($PSBoundParameters.ContainsKey('Number')) {
        $GetDisk = $GetDisk | Where-Object {$_.Number -eq $Number}
    }

    if ($PSBoundParameters.ContainsKey('BootFromDisk')) {$GetDisk = $GetDisk | Where-Object {$_.BootFromDisk -eq $BootFromDisk}}
    if ($PSBoundParameters.ContainsKey('IsBoot'))       {$GetDisk = $GetDisk | Where-Object {$_.IsBoot -eq $IsBoot}}
    if ($PSBoundParameters.ContainsKey('IsReadOnly'))   {$GetDisk = $GetDisk | Where-Object {$_.IsReadOnly -eq $IsReadOnly}}
    if ($PSBoundParameters.ContainsKey('IsSystem'))     {$GetDisk = $GetDisk | Where-Object {$_.IsSystem -eq $IsSystem}}

    if ($BusType)           {$GetDisk = $GetDisk | Where-Object {$_.BusType -in $BusType}}
    if ($BusTypeNot)        {$GetDisk = $GetDisk | Where-Object {$_.BusType -notin $BusTypeNot}}
    if ($MediaType)         {$GetDisk = $GetDisk | Where-Object {$_.MediaType -in $MediaType}}
    if ($MediaTypeNot)      {$GetDisk = $GetDisk | Where-Object {$_.MediaType -notin $MediaTypeNot}}
    if ($PartitionStyle)    {$GetDisk = $GetDisk | Where-Object {$_.PartitionStyle -in $PartitionStyle}}
    if ($PartitionStyleNot) {$GetDisk = $GetDisk | Where-Object {$_.PartitionStyle -notin $PartitionStyleNot}}

    return $GetDisk
}