Such a simple task, one would say, and J'ain't found a satisfiable solution. What J'ai essayé (with music playing through a Bluetooth-connected speaker to really know the state of the radio):
- using devcon en tant qu'administrateur: `devcon disable USB\VID_8087&PID_07DC&REV_0001` (which is the HW ID of my Bluetooth adapter)... requires reboot to work...
- using powershell en tant qu'administrateur: `Disable-NetAdapter "Bluetooth Network Connection 3"` (which is translation of the name of my Bluetooth adapter)... it disables the PAN driver, but a Bluetooth speaker continues playing music...
- using net en tant qu'administrateur: `net stop bthserv`... doesn't actually turn off the radio (BT speaker continues playing music)
- using .NET: [The most relevant page on MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/aa362927%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396) doesn't say a word about turning the adapter on/off.
- using explorer: `ms-settings:bluetooth` or `explorer.exe %LocalAppData%\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Settings\cs-CZ\AAA_SettingsPagePCSystemBluetooth.settingcontent-ms`... opens the Bluetooth settings panel, but I still have to cliquez sur the toggle
I can't believe Microsoft would be so ignorant to not provide such a command...
Turn on/off Bluetooth radio/adapter from cmd/powershell in Windows 10
Re: Turn on/off Bluetooth radio/adapter from cmd/powershell in Windows 10
This is challenging because of the necessary interoperation with WinRT, but it is possible in pure 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
```
To use it, save it is a PS1 file, e.g. `bluetooth.ps1`. If you haven't already, follow the instructions in the Enabling Scripts section of [the PowerShell tag wiki](https://superuser.com/tags/powershell/info) to enable the execution of scripts on your system. Then vous pouvez run it from a PowerShell prompt like this:
```
.\bluetooth.ps1 -BluetoothStatus On
```
To turn Bluetooth off, pass `Off` instead.
To run it from a batch file:
```
powershell -command .\bluetooth.ps1 -BluetoothStatus On
```
**Caveat:** If the Bluetooth Support Service is not running, the script attempts to start it because sinon, WinRT will not see Bluetooth radios. Alas, the service cannot be started if the script is not running en tant qu'administrateur. To make that unnecessary, vous pouvez change the startup type of that service to automatic.
Now for some explanation. The first three lines establish the parameters the script takes. Before beginning in earnest, we assurez-vous the Bluetooth Support Service is running and start it if not. We then load the `System.Runtime.WindowsRuntime` assembly so that we can use the [`WindowsRuntimeSystemExtensions.AsTask`](https://msdn.microsoft.com/en-us/library/hh779747(v=vs.110).aspx) method to convert WinRT-style tasks (which .NET/PowerShell doesn't understand) to .NET [`Task`](https://msdn.microsoft.com/en-us/library/dd321424(v=vs.110).aspx)s. That particular method has a boatload of different parameter sets which seem to trip up PowerShell's overload resolution, so in the next line we get the specific one that takes only a resultful WinRT task. Then we define a function that we'll use several times to extract a result of the appropriate type from an asynchronous WinRT task. Following that function's declaration, we [load two necessary types from WinRT metadata](https://blogs.msdn.microsoft.com/oldnewthing/20180110-00/?p=97755). The remainder of the script is pretty much just a PowerShell translation of the C# code you wrote in your answer; it uses the [`Radio`](https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio) WinRT class to find and configure the Bluetooth radio.
```
[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
```
To use it, save it is a PS1 file, e.g. `bluetooth.ps1`. If you haven't already, follow the instructions in the Enabling Scripts section of [the PowerShell tag wiki](https://superuser.com/tags/powershell/info) to enable the execution of scripts on your system. Then vous pouvez run it from a PowerShell prompt like this:
```
.\bluetooth.ps1 -BluetoothStatus On
```
To turn Bluetooth off, pass `Off` instead.
To run it from a batch file:
```
powershell -command .\bluetooth.ps1 -BluetoothStatus On
```
**Caveat:** If the Bluetooth Support Service is not running, the script attempts to start it because sinon, WinRT will not see Bluetooth radios. Alas, the service cannot be started if the script is not running en tant qu'administrateur. To make that unnecessary, vous pouvez change the startup type of that service to automatic.
Now for some explanation. The first three lines establish the parameters the script takes. Before beginning in earnest, we assurez-vous the Bluetooth Support Service is running and start it if not. We then load the `System.Runtime.WindowsRuntime` assembly so that we can use the [`WindowsRuntimeSystemExtensions.AsTask`](https://msdn.microsoft.com/en-us/library/hh779747(v=vs.110).aspx) method to convert WinRT-style tasks (which .NET/PowerShell doesn't understand) to .NET [`Task`](https://msdn.microsoft.com/en-us/library/dd321424(v=vs.110).aspx)s. That particular method has a boatload of different parameter sets which seem to trip up PowerShell's overload resolution, so in the next line we get the specific one that takes only a resultful WinRT task. Then we define a function that we'll use several times to extract a result of the appropriate type from an asynchronous WinRT task. Following that function's declaration, we [load two necessary types from WinRT metadata](https://blogs.msdn.microsoft.com/oldnewthing/20180110-00/?p=97755). The remainder of the script is pretty much just a PowerShell translation of the C# code you wrote in your answer; it uses the [`Radio`](https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio) WinRT class to find and configure the Bluetooth radio.