private/Get-Win32DiskDriveUsb.ps1

function Get-Win32DiskDriveUsb {
    <#
    .SYNOPSIS
        Returns physical disks connected by USB
 
    .DESCRIPTION
        Queries the Win32_DiskDrive WMI class through the .NET System.Management API
        and returns each installed external physical disk. USB disks can be exposed
        through the SCSI driver stack, so InterfaceType cannot reliably identify them.
        The query requires loaded media larger than 2 GB. Query failures write a
        nonterminating error and return no disk objects. This function does not require the
        Storage PowerShell module.
 
    .EXAMPLE
        PS> Get-Win32DiskDriveUsb
 
        Returns external physical disks with loaded media larger than 2 GB.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Management.ManagementObject. Returns zero or more Win32_DiskDrive objects
        matching the external-media query.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Dependencies:
          Windows Features: Windows Management Instrumentation
          DotNet Classes: System.Management.ManagementObject,
                          System.Management.ManagementObjectSearcher
    #>

    [CmdletBinding()]
    [OutputType([System.Management.ManagementObject])]
    param ()

    Write-Verbose "[$($MyInvocation.MyCommand.Name)] Start"

    try {
        $searcher = [System.Management.ManagementObjectSearcher]::new(
            'root\CIMV2',
            "SELECT * FROM Win32_DiskDrive WHERE MediaType = 'External hard disk media' AND MediaLoaded = TRUE AND Size > 2147483648"
        )

        foreach ($disk in $searcher.Get()) {
            $disk
        }
    }
    catch {
        Write-Error -Message "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Unable to enumerate USB disks. $($_.Exception.Message)" -ErrorAction Continue
    }
    finally {
        if ($null -ne $searcher) {
            $searcher.Dispose()
        }
    }

    Write-Verbose "[$($MyInvocation.MyCommand.Name)] End"
}