PowerShell Bluetooth

Bluetooth Quick Reference

Filtering the Noise

Raw Get-PnpDevice -Class Bluetooth returns 30+ entries (GATT services, attribute profiles, enumerators). Filter to actual hardware:

Get-PnpDevice -Class Bluetooth |
    Where-Object { $_.FriendlyName -notmatch 'Generic|Enumerator|RFCOMM|Service|Profile|Attribute' } |
    Select-Object Status, FriendlyName
List actual devices
Get-PnpDevice -Class Bluetooth |
    Where-Object { $_.FriendlyName -notmatch 'Generic|Enumerator|RFCOMM|Service|Profile|Attribute' } |
    Select-Object Status, FriendlyName | Format-Table
Toggle device (reconnect earbuds/keyboard)
$dev = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like "*Buds*"
Disable-PnpDevice -InstanceId $dev.InstanceId -Confirm:$false
Start-Sleep -Seconds 2
Enable-PnpDevice -InstanceId $dev.InstanceId -Confirm:$false
Toggle Bluetooth radio (kill switch)
$radio = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Intel*Wireless*Bluetooth*'
if ($radio.Status -eq 'OK') {
    Disable-PnpDevice -InstanceId $radio.InstanceId -Confirm:$false
    Write-Host "Bluetooth OFF"
} else {
    Enable-PnpDevice -InstanceId $radio.InstanceId -Confirm:$false
    Write-Host "Bluetooth ON"
}
Check Bluetooth services
Get-Service -Name 'bthserv' | Select-Object Name, Status, StartType
Switch audio to Bluetooth headphones
# One-time: Install-Module -Name AudioDeviceCmdlets -Force
Get-AudioDevice -List
Set-AudioDevice -ID "{GUID-from-list}"

Bluetooth Device Management

List Bluetooth Devices

List all Bluetooth devices (paired and available)
Get-PnpDevice -Class Bluetooth | Select-Object Status, Class, FriendlyName, InstanceId
List only connected Bluetooth devices
Get-PnpDevice -Class Bluetooth | Where-Object Status -eq 'OK' |
    Select-Object FriendlyName, Status, @{N='DeviceId';E={$_.InstanceId -replace '.*\\',''}}
List Bluetooth adapters (radios)
Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Radio*' -or
    Where-Object FriendlyName -like '*Adapter*'
Detailed Bluetooth device inventory
Get-PnpDevice -Class Bluetooth | ForEach-Object {
    $driver = Get-PnpDeviceProperty -InstanceId $_.InstanceId -KeyName 'DEVPKEY_Device_DriverVersion' -ErrorAction SilentlyContinue
    [PSCustomObject]@{
        Name     = $_.FriendlyName
        Status   = $_.Status
        Driver   = $driver.Data
        DeviceId = ($_.InstanceId -split '\\')[-1]
    }
} | Format-Table -AutoSize
Get Bluetooth MAC addresses
Get-PnpDevice -Class Bluetooth | ForEach-Object {
    $mac = ($_.InstanceId -split '\\')[-1]
    if ($mac -match '^[0-9A-F]{12}$') {
        [PSCustomObject]@{
            Device = $_.FriendlyName
            MAC    = $mac -replace '(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})', '$1:$2:$3:$4:$5:$6'
            Status = $_.Status
        }
    }
} | Format-Table
List Bluetooth audio devices specifically
Get-PnpDevice | Where-Object {
    $_.Class -eq 'Bluetooth' -and
    ($_.FriendlyName -match 'Audio|Headphone|Speaker|Earbuds|Buds|AirPods|WH-|WF-|Jabra|Bose')
} | Select-Object FriendlyName, Status
List only actual devices (filter GATT/service noise)
Get-PnpDevice -Class Bluetooth |
    Where-Object { $_.FriendlyName -notmatch 'Generic|Enumerator|RFCOMM|Service|Profile|Attribute' } |
    Select-Object Status, FriendlyName | Format-Table
Raw Get-PnpDevice -Class Bluetooth returns 30+ entries — GATT services, attribute profiles, enumerators. The filter above shows only actual hardware (earbuds, keyboard, mouse, radio adapter).

Connect/Disconnect Devices

Windows lacks native PowerShell Bluetooth connect cmdlets. These methods use device control.
Enable a disabled Bluetooth device
$device = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*WH-1000*'
Enable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false
Disable a Bluetooth device (disconnect)
$device = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*WH-1000*'
Disable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false
Toggle device (quick reconnect)
$deviceName = "WH-1000XM4"
$device = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like "*$deviceName*"
Disable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false
Start-Sleep -Seconds 2
Enable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false
Connect using DevCon (Windows SDK required)
# DevCon path after Windows SDK install
$devcon = "C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe"

# List Bluetooth devices
& $devcon find "BTHENUM\*"

# Enable device by hardware ID
& $devcon enable "BTHENUM\Dev_AABBCCDDEEFF"

Bluetooth Radio Control

Check if Bluetooth radio is enabled
Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Radio*' |
    Select-Object FriendlyName, Status
Disable Bluetooth radio (turn off Bluetooth)
Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Radio*' |
    Disable-PnpDevice -Confirm:$false
Enable Bluetooth radio (turn on Bluetooth)
Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Radio*' |
    Enable-PnpDevice -Confirm:$false
Toggle Bluetooth radio
$radio = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Radio*'
if ($radio.Status -eq 'OK') {
    Disable-PnpDevice -InstanceId $radio.InstanceId -Confirm:$false
    Write-Host "Bluetooth OFF" -ForegroundColor Yellow
} else {
    Enable-PnpDevice -InstanceId $radio.InstanceId -Confirm:$false
    Write-Host "Bluetooth ON" -ForegroundColor Green
}

WMI/CIM Bluetooth Queries

Get Bluetooth devices via CIM (alternative method)
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_PnPEntity |
    Where-Object { $_.PNPClass -eq 'Bluetooth' } |
    Select-Object Name, Status, PNPDeviceID
Get Bluetooth device properties
Get-CimInstance -Namespace root/cimv2 -ClassName Win32_PnPEntity |
    Where-Object { $_.PNPClass -eq 'Bluetooth' -and $_.Name -notlike '*Radio*' } |
    Select-Object Name, Manufacturer, Status, ConfigManagerErrorCode
Check Bluetooth service status
Get-Service -Name 'bthserv' | Select-Object Name, Status, StartType
Get-Service -Name 'BthHFSrv' | Select-Object Name, Status, StartType  # Handsfree
Get-Service -Name 'BluetoothUserService_*' | Select-Object Name, Status
Restart Bluetooth services
Restart-Service -Name 'bthserv' -Force
Restart-Service -Name 'BthHFSrv' -Force -ErrorAction SilentlyContinue

Bluetooth Audio Device Control

List audio endpoints (includes Bluetooth audio)
Get-PnpDevice -Class AudioEndpoint | Where-Object Status -eq 'OK' |
    Select-Object FriendlyName, Status, InstanceId
Set default audio device (requires AudioDeviceCmdlets module)
# Install module first (one-time)
Install-Module -Name AudioDeviceCmdlets -Force

# List audio devices
Get-AudioDevice -List

# Set default playback device
Set-AudioDevice -ID "{GUID-from-list}"
Quick switch to Bluetooth headphones
# Requires AudioDeviceCmdlets module
$btDevice = Get-AudioDevice -List | Where-Object Name -like '*WH-1000*'
if ($btDevice) {
    Set-AudioDevice -ID $btDevice.ID
    Write-Host "Switched to: $($btDevice.Name)"
}

Troubleshooting

Check for Bluetooth driver issues
Get-PnpDevice -Class Bluetooth | ForEach-Object {
    $problem = (Get-PnpDeviceProperty -InstanceId $_.InstanceId -KeyName 'DEVPKEY_Device_ProblemCode' -ErrorAction SilentlyContinue).Data
    [PSCustomObject]@{
        Device  = $_.FriendlyName
        Status  = $_.Status
        Problem = if ($problem) { $problem } else { 'None' }
    }
} | Format-Table
Reset Bluetooth stack
# Disable all Bluetooth devices
Get-PnpDevice -Class Bluetooth | Disable-PnpDevice -Confirm:$false

# Restart Bluetooth services
Restart-Service -Name 'bthserv' -Force

# Re-enable devices
Start-Sleep -Seconds 3
Get-PnpDevice -Class Bluetooth | Enable-PnpDevice -Confirm:$false
Export Bluetooth device inventory to CSV
Get-PnpDevice -Class Bluetooth | Select-Object FriendlyName, Status, InstanceId,
    @{N='MAC';E={($_.InstanceId -split '\\')[-1]}} |
    Export-Csv -Path "$env:USERPROFILE\Desktop\bluetooth-devices.csv" -NoTypeInformation
Check Bluetooth event logs
Get-WinEvent -LogName 'Microsoft-Windows-Bluetooth-BthLEPrepairing/Operational' -MaxEvents 20 |
    Select-Object TimeCreated, Message | Format-Table -Wrap
Verify Bluetooth hardware ID
Get-PnpDevice -Class Bluetooth | ForEach-Object {
    $hwid = (Get-PnpDeviceProperty -InstanceId $_.InstanceId -KeyName 'DEVPKEY_Device_HardwareIds' -ErrorAction SilentlyContinue).Data
    [PSCustomObject]@{
        Name       = $_.FriendlyName
        HardwareID = ($hwid | Select-Object -First 1)
    }
} | Format-Table -AutoSize

Quick Reference

Daily driver commands
# List paired devices
Get-PnpDevice -Class Bluetooth | Select-Object FriendlyName, Status

# Is my headset connected?
Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*WH-1000*'

# Toggle Bluetooth radio
$r = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Radio*'
if ($r.Status -eq 'OK') { Disable-PnpDevice -InstanceId $r.InstanceId -Confirm:$false } else { Enable-PnpDevice -InstanceId $r.InstanceId -Confirm:$false }

# Reconnect problematic device
$d = Get-PnpDevice -Class Bluetooth | Where-Object FriendlyName -like '*Sony*'
Disable-PnpDevice -InstanceId $d.InstanceId -Confirm:$false; Start-Sleep 2; Enable-PnpDevice -InstanceId $d.InstanceId -Confirm:$false