有人会说,这是一个非常简单的任务,但我还没有找到令人满意的解决方案。我尝试过(通过蓝牙连接的扬声器播放音乐以真正了解收音机的状态):
- 以管理员身份使用 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:bluetooth
或explorer.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 的方法Task
s。该特定方法具有大量不同的参数集,这些参数集似乎会破坏 PowerShell 的重载解析,因此在下一行中,我们获得了仅接受结果 WinRT 任务的特定方法。然后我们定义一个函数,我们将多次使用该函数从异步 WinRT 任务中提取适当类型的结果。在该函数声明之后,我们从 WinRT 元数据中加载两种必要的类型。脚本的其余部分基本上只是您在答案中编写的 C# 代码的 PowerShell 翻译;它使用Radio
WinRT 类来查找和配置蓝牙无线电。
答案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>"
不需要重新启动。