private/Disk/Get-OSDeployVolumeUSB.ps1

function Get-OSDeployVolumeUSB {
    <#
    .SYNOPSIS
        Returns all volumes that reside on USB-connected disks.
 
    .DESCRIPTION
        Enumerates USB disks using Get-OSDeployDisk, collects their partition access paths,
        and returns the matching volumes with drive letter, label, size, and health
        properties. An optional -FileSystemLabel parameter narrows results to volumes
        whose label matches the supplied value.
 
    .PARAMETER FileSystemLabel
        Optional. When specified, only volumes whose FileSystemLabel matches this value
        are returned.
 
    .OUTPUTS
        Selected.Microsoft.Management.Infrastructure.CimInstance
 
    .EXAMPLE
        Get-OSDeployVolumeUSB
 
    .EXAMPLE
        Get-OSDeployVolumeUSB -FileSystemLabel 'OSDEPLOY'
 
    .NOTES
        Author: David Segura
        Company: Recast Software
 
    Dependencies:
            PowerShell Modules: Storage
            .NET Classes: [Microsoft.Management.Infrastructure.CimSession], [Microsoft.Management.Infrastructure.CimInstance]
      Module Functions: Get-OSDeployDisk
    #>

    [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 "[$($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()
        }
    }
}