Activer/désactiver la radio/l'adaptateur Bluetooth depuis cmd/powershell sous Windows 10

Une tâche si simple, dirait-on, et je n’ai pas trouvé de solution satisfaisante. Ce que j’ai essayé (avec de la musique jouant via une enceinte connectée en Bluetooth pour vraiment connaître l’état de la radio) :

  • Utiliser devcon en tant qu’administrateur : devcon disable USB\VID_8087&PID_07DC&REV_0001 (qui est l’identifiant matériel de mon adaptateur Bluetooth)… nécessite un redémarrage pour fonctionner…

  • Utiliser powershell en tant qu’administrateur : Disable-NetAdapter "Bluetooth Network Connection 3" (qui est la traduction du nom de mon adaptateur Bluetooth)… il désactive le pilote PAN, mais une enceinte Bluetooth continue de jouer de la musique…

  • Utiliser net en tant qu’administrateur : net stop bthserv… ne coupe pas réellement la radio (l’enceinte BT continue de jouer de la musique)

  • Utiliser .NET : La page la plus pertinente sur MSDN ne dit pas un mot sur l’activation/désactivation de l’adaptateur.

  • Utiliser l’explorateur : ms-settings:bluetooth ou explorer.exe %LocalAppData%\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Settings\cs-CZ\AAA_SettingsPagePCSystemBluetooth.settingcontent-ms… ouvre le panneau de paramètres Bluetooth, mais je dois quand même cliquer sur le bouton bascule

Je n’arrive pas à croire que Microsoft serait assez négligent pour ne pas fournir une telle commande…


Source : Super User

C’est un défi en raison de l’interopération nécessaire avec WinRT, mais c’est possible en pur PowerShell :

[CmdletBinding()] Param (
    [Parameter(Mandatory=$true)][ValidateSet('Off', 'On')][string]$BluetoothStatus
)
If ((Get-Service bthserv).Status -eq 'Stopped') { Start-Service bthserv }
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' })[0]
Function Await($WinRtTask, $ResultType) {
    $asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $netTask.Wait(-1) | Out-Null
    $netTask.Result
}
[Windows.Devices.Radios.Radio,Windows.System.Devices,ContentType=WindowsRuntime] | Out-Null
[Windows.Devices.Radios.RadioAccessStatus,Windows.System.Devices,ContentType=WindowsRuntime] | Out-Null
Await ([Windows.Devices.Radios.Radio]::RequestAccessAsync()) ([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null
$radios = Await ([Windows.Devices.Radios.Radio]::GetRadiosAsync()) ([System.Collections.Generic.IReadOnlyList[Windows.Devices.Radios.Radio]])
$bluetooth = $radios | ? { $_.Kind -eq 'Bluetooth' }
[Windows.Devices.Radios.RadioState,Windows.System.Devices,ContentType=WindowsRuntime] | Out-Null
Await ($bluetooth.SetStateAsync($BluetoothStatus)) ([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null

Pour l’utiliser, enregistrez-le comme fichier PS1, par exemple bluetooth.ps1. Si ce n’est pas déjà fait, suivez les instructions de la section Activation des scripts du wiki du tag powershell pour activer l’exécution de scripts sur votre système. Ensuite vous pouvez l’exécuter depuis une invite PowerShell comme ceci :

.\bluetooth.ps1 -BluetoothStatus On

Pour désactiver le Bluetooth, passez Off à la place.

Pour l’exécuter depuis un fichier batch :

powershell -command .\bluetooth.ps1 -BluetoothStatus On

Mise en garde : Si le Service de support Bluetooth n’est pas en cours d’exécution, le script tente de le démarrer car sinon, WinRT ne verra pas les radios Bluetooth. Hélas, le service ne peut pas être démarré si le script ne s’exécute pas en tant qu’administrateur. Pour rendre cela inutile, vous pouvez changer le type de démarrage de ce service en automatique.

Maintenant quelques explications. Les trois premières lignes établissent les paramètres que le script accepte. Avant de commencer sérieusement, nous nous assurons que le Service de support Bluetooth est en cours d’exécution et le démarrons sinon. Nous chargeons ensuite l’assembly System.Runtime.WindowsRuntime pour pouvoir utiliser la méthode WindowsRuntimeSystemExtensions.AsTask pour convertir les tâches de style WinRT (que .NET/PowerShell ne comprend pas) en Task .NET. Cette méthode particulière a une quantité énorme de jeux de paramètres différents qui semblent perturber la résolution de surcharge de PowerShell, donc dans la ligne suivante nous obtenons celui spécifique qui ne prend qu’une tâche WinRT avec résultat. Ensuite nous définissons une fonction que nous utiliserons plusieurs fois pour extraire un résultat du type approprié d’une tâche WinRT asynchrone. Après la déclaration de cette fonction, nous chargeons deux types nécessaires depuis les métadonnées WinRT. Le reste du script est essentiellement une traduction PowerShell du code C# que vous avez écrit dans votre réponse ; il utilise la classe WinRT Radio pour trouver et configurer la radio Bluetooth.