在 Windows 10 中通过 cmd/powershell 打开/关闭蓝牙无线电/适配器

在 Windows 10 中通过 cmd/powershell 打开/关闭蓝牙无线电/适配器

有人会说,这是一个非常简单的任务,但我还没有找到令人满意的解决方案。我尝试过(通过蓝牙连接的扬声器播放音乐以真正了解收音机的状态):

  • 以管理员身份使用 devcon:(devcon disable USB\VID_8087&PID_07DC&REV_0001这是我的蓝牙适配器的硬件 ID)...需要重新启动才能工作...
  • 以管理员身份使用 powershell:(Disable-NetAdapter "Bluetooth Network Connection 3"这是我的蓝牙适配器名称的翻译)...它禁用了 PAN 驱动程序,但蓝牙扬声器继续播放音乐...
  • 以管理员身份使用网络:net stop bthserv...实际上并没有关闭收音机(蓝牙扬声器继续播放音乐)
  • 使用.NET:MSDN 上最相关的页面没有提及打开/关闭适配器。
  • 使用资源管理器:ms-settings:bluetoothexplorer.exe %LocalAppData%\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Settings\cs-CZ\AAA_SettingsPagePCSystemBluetooth.settingcontent-ms...打开蓝牙设置面板,但我仍然必须单击切换

我不敢相信微软竟然如此无知,不提供这样的命令......

答案1

由于需要与 WinRT 进行互操作,因此这很有挑战性,但在纯 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

要使用它,请将其保存为 PS1 文件,例如bluetooth.ps1。如果您还没有这样做,请按照启用脚本部分中的说明进行操作PowerShell 标签 wiki以启用系统上的脚本执行。然后您可以从 PowerShell 提示符运行它,如下所示:

.\bluetooth.ps1 -BluetoothStatus On

要关闭蓝牙,请通过Off

要从批处理文件运行它:

powershell -command .\bluetooth.ps1 -BluetoothStatus On

警告:如果蓝牙支持服务未运行,脚本将尝试启动它,否则 WinRT 将看不到蓝牙无线电。遗憾的是,如果脚本未以管理员身份运行,则无法启动该服务。为了避免这种情况,您可以将该服务的启动类型更改为自动。

现在来解释一下。前三行确定了脚本所采用的参数。在开始之前,我们先确保蓝牙支持服务正在运行,如果没有,则启动它。然后我们加载程序System.Runtime.WindowsRuntime集,以便我们可以使用WindowsRuntimeSystemExtensions.AsTask将 WinRT 样式的任务(.NET/PowerShell 无法理解)转换为 .NET 的方法Tasks。该特定方法具有大量不同的参数集,这些参数集似乎会破坏 PowerShell 的重载解析,因此在下一行中,我们获得了仅接受结果 WinRT 任务的特定方法。然后我们定义一个函数,我们将多次使用该函数从异步 WinRT 任务中提取适当类型的结果。在该函数声明之后,我们从 WinRT 元数据中加载两种必要的类型。脚本的其余部分基本上只是您在答案中编写的 C# 代码的 PowerShell 翻译;它使用RadioWinRT 类来查找和配置蓝牙无线电。

答案2

在放弃寻找现成的解决方案后,我发现通用 Windows 平台应用程序可以访问无线电控制API

因此,我将示例无线电控制应用程序与命令行控制应用程序合并,结果如下:https://github.com/peci1/RadioControl。 它是在 Windows 应用商店上发布

一般来说,不可能让应用程序在后台运行,因此你需要先启动 GUI,然后可以从命令行调用它,例如

radiocontrol.exe 0 on
radiocontrol.exe Bluetooth off

此应用程序所需的核心功能是:

using Windows.Devices.Radios;
await Radio.RequestAccessAsync();
var radios = await Radio.GetRadiosAsync();
await radios[0].SetStateAsync(RadioState.On);

然后您还需要将 Radios 功能添加到应用程序清单中:

<DeviceCapability Name="radios" />

为了允许从命令行进行控制,您需要重写protected override async void OnActivated(IActivatedEventArgs args)App.xaml.cs 中的方法并在分支中执行处理,如下所示:

switch (args.Kind)
        {
            case ActivationKind.CommandLineLaunch:

答案3

这个 Autohotkey 脚本似乎可以解决问题。我对此感到困扰Sleep,但似乎窗口在准备好接收我的击键之前就处于活动状态。

SendMode Input
Run, ms-settings:bluetooth
WinWaitActive, Settings
Sleep 300
Send,{Tab}{Space}
WinClose, A

交叉发布至https://stackoverflow.com/q/48700268/308851弄清楚Sleep 300可以用什么来替代它。

答案4

使用 pnputil 怎么样?

pnputil /disable-device "<device instance ID>"
pnputil /enable-device "<device instance ID>"

不需要重新启动。

相关内容