从 Windows 10 中的 cmd/powershell 打开/关闭蓝牙无线电/适配器

Mar*_*cka 36 windows bluetooth command-line windows-10

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

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

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

Ben*_*n N 36

由于与 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
Run Code Online (Sandbox Code Playgroud)

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

.\bluetooth.ps1 -BluetoothStatus On
Run Code Online (Sandbox Code Playgroud)

要关闭蓝牙,请Off改为通过。

要从批处理文件运行它:

powershell -command .\bluetooth.ps1 -BluetoothStatus On
Run Code Online (Sandbox Code Playgroud)

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

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

  • 不能在空值表达式上调用方法。在 C:\Users\chx\AppData\Local\Microsoft\WindowsApps\bluetooth.ps1:18 char:1 + Await ($bluetooth.SetStateAsync($BluetoothStatus)) ([Windows.Devices. (2认同)
  • 聪明,有效!我只是无法使用此 API 编译桌面应用程序,但在脚本中动态加载它似乎是要走的路。现在,与 Linux 上的 `rfkill unblock bluetooth` 进行比较:-D (2认同)
  • 要调整此脚本,使其本身检查蓝牙是否打开(或关闭)并停止(或启动),请参阅 https://superuser.com/q/1494499 (2认同)

Mar*_*cka 6

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

所以我将一个示例无线电控制应用程序与一个命令行控制的应用程序合并,结果在这里:https : //github.com/peci1/RadioControl。它已在 Windows Store发布

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

radiocontrol.exe 0 on
radiocontrol.exe Bluetooth off
Run Code Online (Sandbox Code Playgroud)

这个应用程序需要的核心功能是:

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

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

<DeviceCapability Name="radios" />
Run Code Online (Sandbox Code Playgroud)

并且要允许从命令行进行控制,您需要覆盖protected override async void OnActivated(IActivatedEventArgs args)App.xaml.cs 中的方法并在这样的分支中进行处理:

switch (args.Kind)
        {
            case ActivationKind.CommandLineLaunch:
Run Code Online (Sandbox Code Playgroud)


chx*_*chx 6

这个 Autohotkey 脚本似乎可以解决问题。我对那里感到困扰Sleep,但似乎窗口在准备好接收我的击键之前就变得活跃了。

SendMode Input
Run, ms-settings:bluetooth
WinWaitActive, Settings
Sleep 300
Send,{Tab}{Space}
WinClose, A
Run Code Online (Sandbox Code Playgroud)

交叉发布到/sf/ask/3409018791/以找出Sleep 300可以替换的内容。