private/Get-OSDeployVolumeUSB.ps1

function Get-OSDeployVolumeUSB {
    <#
    .SYNOPSIS
        Gets volumes hosted on USB-connected disks
 
    .DESCRIPTION
        Uses Get-OSDeployDisk to find online USB disks, queries local MSFT_Partition and
        MSFT_Volume instances, and matches volumes to USB partition access paths. Returned
        rows contain selected identity, filesystem, capacity, and health properties.
        Provider failures write a nonterminating error and return no objects.
 
    .PARAMETER FileSystemLabel
        Filters results to volumes whose FileSystemLabel exactly equals the supplied value.
        When omitted, all matched USB volumes are returned.
 
    .EXAMPLE
        PS> Get-OSDeployVolumeUSB -FileSystemLabel 'OSDEPLOY'
 
        Returns USB volumes whose filesystem label is OSDEPLOY.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Management.Automation.PSCustomObject. Returns zero or more selected volume
        rows with DriveLetter, FileSystemLabel, FileSystem, SizeGB, SizeRemainingGB,
        SizeRemainingMB, DriveType, OperationalStatus, HealthStatus, and UniqueId.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Dependencies:
          Module Functions: Get-OSDeployDisk
          PowerShell Modules: Storage
          Windows Features: Windows Storage Management provider
          DotNet Classes: Microsoft.Management.Infrastructure.CimSession,
                          System.Management.Automation.PSCustomObject
    #>

    [CmdletBinding()]
    param (
        [string]$FileSystemLabel
    )

    # Get-OSDeployDisk filters out offline disks and card readers with no media
    $UsbDisks = Get-OSDeployDisk -BusType USB
    if (-not $UsbDisks) { return }

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

    try {
        # Storage supplies the MSFT_Partition and MSFT_Volume type data used by downstream Storage cmdlets.
        Import-Module Storage -ErrorAction Stop

        $CimSession = [Microsoft.Management.Infrastructure.CimSession]::Create($env:COMPUTERNAME)
        $Partitions = @($CimSession.QueryInstances($StorageNamespace, 'WQL', 'SELECT * FROM MSFT_Partition'))
        $VolumesRaw = @($CimSession.QueryInstances($StorageNamespace, 'WQL', 'SELECT * FROM MSFT_Volume'))

        # Collect all access paths from USB partitions; skip partitions with no mount point
        $UsbAccessPaths = $Partitions |
            Where-Object { $_.DiskNumber -in $UsbDisks.Number -and $null -ne $_.AccessPaths } |
            Select-Object -ExpandProperty AccessPaths
        if (-not $UsbAccessPaths) { return }

        # Match volumes by GUID path, which is present in both MSFT_Volume.Path and MSFT_Partition.AccessPaths
        $Volumes = $VolumesRaw | Sort-Object DriveLetter |
            Where-Object { $_.Path -in $UsbAccessPaths } |
            Select-Object DriveLetter, FileSystemLabel, FileSystem,
                @{Name = 'SizeGB';          Expression = { [int]($_.Size / 1GB) }},
                @{Name = 'SizeRemainingGB'; Expression = { [int]($_.SizeRemaining / 1GB) }},
                @{Name = 'SizeRemainingMB'; Expression = { [int]($_.SizeRemaining / 1MB) }},
                DriveType, OperationalStatus, HealthStatus, UniqueId

        if ($PSBoundParameters.ContainsKey('FileSystemLabel')) {
            return ($Volumes | Where-Object { $_.FileSystemLabel -eq $FileSystemLabel })
        }

        return $Volumes
    }
    catch {
        Write-Error -Message "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Unable to enumerate USB volumes by using the Storage CIM provider. $($_.Exception.Message)" -ErrorAction Continue
        return
    }
    finally {
        if ($null -ne $CimSession) {
            $CimSession.Dispose()
        }
    }
}