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


28

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

  • 使用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...打开“蓝牙设置”面板,但我仍然必须单击切换

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


您如何播放音乐?
harrymc '18

使用Winamp :)
Martin Pecka,

杀死Winamp会停止音乐吗?
harrymc '18

当然,为什么不呢?但是问题不在于停止音乐播放,而在于对BT收音机的控制。
马丁·佩卡

1
@harrymc请阅读问题。音乐播放只是我检测蓝牙连接是否存在的一种方式。我真正感兴趣的是一种禁用/启用蓝牙适配器的方法。
马丁·佩卡

Answers:


21

由于与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将看不到蓝牙无线电。las,如果脚本未以管理员身份运行,则无法启动服务。为了避免这种情况,您可以将该服务的启动类型更改为自动。

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


1
您不能在空值表达式上调用方法。在C:\ Users \ chx \ AppData \ Local \ Microsoft \ WindowsApps \ bluetooth.ps1:18 char:1 + Await($ bluetooth.SetStateAsync($ BluetoothStatus))([Windows.Devices。–
chx

@chx您确定您的机器具有蓝牙适配器吗?如果没有蓝牙无线电,倒数第二行将设置$bluetooth为null,这将导致倒数第二行产生该错误。
本N

我100%确信它在“设置”应用中可见,并且我以无线方式收听音乐,并且设备管理器和wmic也会报告它。
chx

@chx嗯,如果用just代替最后三行,会得到什么$radios?这将显示WinRT返回的无线电列表。
本N

2
聪明,行得通!我只是无法使用此API编译桌面应用程序,但是将其动态加载到脚本中似乎是可行的方法。现在,与rfkill unblock bluetooth在Linux上进行比较:-D
Martin Pecka,

5

放弃寻求现成的解决方案后,我发现Universal Windows Platform应用程序可以访问无线电控制API

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

通常,不可能只让应用程序在后台运行,因此您需要先启动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:

这个答案更适合StackOverflow。
harrymc '18

@MartinPecka偶然地,您知道如何重新连接使用断开连接的蓝牙硬件Disable/Enable-NetAdapter吗? superuser.com/questions/1444278/...
JinSnow

3

这个Autohotkey脚本似乎可以解决问题。我被Sleep那里打扰了,但似乎该窗口在准备好接收我的击键之前就被激活了。

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

交叉发布到/programming//q/48700268/308851,以找出Sleep 300可以替换的内容。


在大多数情况下,这也可能是一个解决方案。发送击键后,我还需要增加短暂的睡眠。如果屏幕被锁定,此解决方案将无法正常工作。我上面发布的通用Windows应用程序即使在锁定屏幕的情况下也能正常工作。
马丁·佩卡

2

这是部分解决方案:wmic path Win32_PNPEntity where "caption like '%bluetooth%' AND DeviceID like 'USB\\%'" call disable当然可以使Bluetooth On / Off开关消失,并且Device Manager报告This device is disabled. (Code 22)。我不确定这是否足以杀死收音机。

我找不到有关call接受参数的文档。我认为这里应该有某种形式rfkill


很抱歉,按照您的描述对我不起作用。对我来说,蓝牙播放停止,但是控制面板中的所有蓝牙开关都保持打开状态。和通话enable不会恢复蓝牙播放。有关PNPEntity类的文档位于:msdn.microsoft.com/zh-cn/library/aa394353 ( v=vs.85).aspx ,但似乎没有其他有用的方法……
Martin Pecka

1

您可以使用DevManView使用以下语法从命令行启用/禁用设备:

devmanview /disable <Device Name>   
devmanview /enable <Device Name>    

它还允许在/use_wildcard参数中使用通配符。


Devmanview确实是一个有用的工具,但是并不能解决我的问题。问题在于似乎没有设备可以在设备管理器中禁用以关闭蓝牙无线电。
Martin Pecka '18

@MartinPecka您没有看到这些吗?i.stack.imgur.com/UrOuc.png如果没有,您可能想要尝试更新驱动程序...
rahuldottech

我确实看到了蓝牙设备,但是禁用它并不会停止播放-可能是因为需要重新启动系统才能使其真正变为禁用状态(如原始问题所述)。
马丁·佩卡

0

Powershell的cmdlet可以完全满足您的要求:

https://gallery.technet.microsoft.com/PowerShell-Device-60d73bb0

使用Get-Device获取设备列表。您可以通过管道通过where对象选择设备,然后将其通过管道传输到Disable-Device或Enable-Device。

详细说明...

下载并解压缩文件。

以管理员身份启动Powershell。

如有必要,更改执行策略:

Set-ExecutionPolicy Unrestricted

导入模块:

Import-Module .\DeviceManagement.psd1

如果您需要缩小设备列表的范围,可以使用-like比较:

Get-Device | Where-Object {$_.Name -like '*bluetooth*'}

如果您知道确切的名称,则可以使用-eq(等于)进行比较:

Get-Device | Where-Object {$_.Name -eq 'Martin's Bluetooth Adapter'} | Disable-Device -Confirm:$False

擦拭裤子上的手。


这将禁用USB设备,而不仅仅是无线电。wmic也可以做到这一点,至少我是这样认为的。
chx

问题并没有询问如何禁用广播,而不询问适配器。为什么要区分?如果您可以给我一个很好的理由,我将考虑为您进行挖掘,但是我回答了一个问题:“我真正感兴趣的是一种禁用/启用Bluetooth适配器的方法。– Martin Pecka 2月5日在9:31“
世界末日'18

抱歉,适配器和收音机有什么区别?我认为这两个术语是等效的。硬件可以提供大量的软件设备,您是对的,这个问题与它们无关。
Martin Pecka '18

而且,这和里卡多·门德斯(Ricardo Mendes)的2012 PS脚本在我的Win 10 1709 64bit上均不起作用,正如他们的评论中所述。两者都以错误结尾Disable-Device : Error calling SetupDiCallClassInstaller。我以管理员身份使用不受限制的执行策略来运行它们。
Martin Pecka '18

0

我制作了一个批处理脚本,用于检查reg键值,该值仅在启用了蓝牙无线电的情况下才可用。然后,它使用正确的参数调用上面的Ben N的powershell脚本,以切换其当前状态。将其变成切换快捷方式,而不必分别使用打开和关闭。

@echo off
FOR /F "skip=2 tokens=2,*" %%A IN ('reg.exe query "HKLM\SYSTEM\CurrentControlSet\Services\bthserv\Parameters\BluetoothControlPanelTasks" /v "state"') DO set "VAR=%%B"

if %VAR%==0x1 (goto ON)

Powershell.exe -executionpolicy remotesigned -windowstyle hidden -File ".\bluetooth.ps1" -BluetoothStatus On
goto end

:ON
Powershell.exe -executionpolicy remotesigned -windowstyle hidden -File ".\bluetooth.ps1" -BluetoothStatus Off

:end

-1

从命令提示符处(以管理员身份)执行以下命令即可达到目的:

netsh interface set interface name="Bluetooth Network Connection" admin=disabled

我以前曾使用相同的命令来禁用我的Wi-Fi适配器,并发现它也可以与其他适配器一起使用:控制面板>网络和Internet>网络连接。只需将“名称”参数更改为适配器的名称。您也可以通过将最后一个参数更改为来再次启用它admin=enabled


1
这似乎也只是禁用了PAN驱动程序,但并没有关闭无线电设备本身(在控制面板中,蓝牙仍被报告为“开”)。
Martin Pecka '17

现在已通过蓝牙repro测试验证,不会关闭蓝牙。
Martin Pecka '17

抱歉@ peci1,我误解了您的问题。我以前一直在研究与禁用蓝牙有关的问题,并将您的问题解释为相同。因此,您的目标是关闭(切断电源)蓝牙设备?我会研究一下,让我知道是否发现任何东西。
Micah Vertal

@ peci1 这个链接对您有帮助吗?
Micah Vertal

不,不是的。这是关于USB而不是蓝牙设备的。而且,链接的设备管理Cmdlet也不起作用。
马丁·佩卡
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.