Ligar / desligar o adaptador / rádio Bluetooth do cmd / powershell no Windows 10

28

Uma tarefa tão simples, diríamos, e não encontrei uma solução satisfatória. O que eu tentei (com a música tocando em um alto-falante conectado por Bluetooth para realmente saber o estado do rádio):

  • usando o devcon como administrador: devcon disable USB\VID_8087&PID_07DC&REV_0001(que é o ID HW do meu adaptador Bluetooth) ... requer reinicialização para funcionar ...
  • usando o powershell como administrador: Disable-NetAdapter "Bluetooth Network Connection 3"(que é a tradução do nome do meu adaptador Bluetooth) ... desativa o driver PAN, mas um alto-falante Bluetooth continua tocando música ...
  • usando net como administrador: net stop bthserv... na verdade, não desliga o rádio (o alto-falante BT continua tocando música)
  • usando o .NET: A página mais relevante no MSDN não diz nada sobre como ligar / desligar o adaptador.
  • usando o explorer: ms-settings:bluetoothou explorer.exe %LocalAppData%\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Settings\cs-CZ\AAA_SettingsPagePCSystemBluetooth.settingcontent-ms... abre o painel de configurações do Bluetooth, mas ainda preciso clicar no botão de alternância

Não acredito que a Microsoft seria tão ignorante em não fornecer esse comando ...

Martin Pecka
fonte
Como você está tocando a música?
21918 harrymc
Usando Winamp :)
Martin Pecka
Matar o Winamp para a música?
harrymc
Claro, por que não? Mas a questão não é parar a reprodução de música, é sobre o controle do rádio BT.
Martin Pecka
1
@harrymc Leia a pergunta, por favor. A reprodução de música é apenas uma maneira de detectar se a conexão Bluetooth está ativa ou não. O que realmente me interessa é realmente uma maneira de desativar / ativar o adaptador Bluetooth.
Martin Pecka

Respostas:

21

Isso é desafiador devido à interoperação necessária com o WinRT, mas é possível no PowerShell puro:

[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

Para usá-lo, salve-o como um arquivo PS1, por exemplo bluetooth.ps1. Se você ainda não o fez, siga as instruções na seção Habilitando scripts do wiki de tags do PowerShell para habilitar a execução de scripts no seu sistema. Em seguida, você pode executá-lo em um prompt do PowerShell como este:

.\bluetooth.ps1 -BluetoothStatus On

Para desativar o Bluetooth, passe em seu Offlugar.

Para executá-lo a partir de um arquivo em lotes:

powershell -command .\bluetooth.ps1 -BluetoothStatus On

Advertência: Se o Serviço de Suporte Bluetooth não estiver em execução, o script tentará iniciá-lo porque, caso contrário, o WinRT não verá rádios Bluetooth. Infelizmente, o serviço não pode ser iniciado se o script não estiver sendo executado como administrador. Para tornar isso desnecessário, você pode alterar o tipo de inicialização desse serviço para automático.

Agora, para algumas explicações. As três primeiras linhas estabelecem os parâmetros utilizados pelo script. Antes de começar a sério, garantimos que o Serviço de Suporte Bluetooth esteja em execução e o inicie, se não estiver. Em seguida, carregamos o System.Runtime.WindowsRuntimeassembly para que possamos usar o WindowsRuntimeSystemExtensions.AsTaskmétodo para converter tarefas no estilo WinRT (que o .NET / PowerShell não entende) em .NET Tasks. Esse método específico possui uma carga de conjuntos de parâmetros diferentes que parecem disparar a resolução de sobrecarga do PowerShell; portanto, na próxima linha, obtemos o específico que executa apenas uma tarefa do WinRT resultante. Em seguida, definimos uma função que usaremos várias vezes para extrair um resultado do tipo apropriado de uma tarefa assíncrona do WinRT. Após a declaração dessa função, carregamos dois tipos necessários dos metadados do WinRT. O restante do script é basicamente uma tradução do código C # que você escreveu na resposta do PowerShell; ele usa a Radioclasse WinRT para encontrar e configurar o rádio Bluetooth.

Ben N
fonte
1
Você não pode chamar um método em uma expressão de valor nulo. Em C: \ Users \ chx \ AppData \ Local \ Microsoft \ WindowsApps \ bluetooth.ps1: 18 char: 1 + Aguardar ($ bluetooth.SetStateAsync ($ BluetoothStatus)) ([Windows.Devices.
chx
@chx Tem certeza de que sua máquina possui um adaptador Bluetooth? Se não houver rádio Bluetooth, a penúltima linha será definida $bluetoothcomo nula, o que fará com que a penúltima linha produza esse erro.
Ben
Tenho 100% de certeza de que está visível no aplicativo "Configurações" e ouço música sem fio, e o Device Manager e a wmic também a reportam.
CHX
@chx Hmm, o que você ganha se substituir as últimas três linhas por apenas $radios? Isso mostrará a lista de rádios que o WinRT retornou.
Ben Ben
2
Inteligente, funciona! Eu simplesmente não conseguia compilar um aplicativo de desktop usando essa API, mas carregá-lo dinamicamente em um script parece ser o caminho a percorrer. Agora, compare com o rfkill unblock bluetoothLinux :-D
Martin Pecka
5

Depois de desistir de procurar soluções prontas, descobri que os aplicativos da Plataforma Universal do Windows têm acesso à API de controle de rádio .

Então, mesclei um aplicativo de controle de rádio de amostra com um aplicativo controlado por linha de comando e o resultado está aqui: https://github.com/peci1/RadioControl . É publicado na Windows Store .

Em geral, não é possível deixar o aplicativo ser executado em segundo plano, portanto, é necessário iniciar a GUI primeiro e, em seguida, chamá-lo na linha de comando, como

radiocontrol.exe 0 on
radiocontrol.exe Bluetooth off

Os principais recursos que este aplicativo precisa são:

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

Em seguida, você também precisa adicionar o recurso Rádios ao manifesto do aplicativo:

<DeviceCapability Name="radios" />

E para permitir o controle da linha de comando, você precisa substituir o método protected override async void OnActivated(IActivatedEventArgs args)no App.xaml.cs e fazer o processamento em uma ramificação como esta:

switch (args.Kind)
        {
            case ActivationKind.CommandLineLaunch:
Martin Pecka
fonte
Essa resposta se encaixa melhor no StackOverflow.
harrymc
@MartinPecka Por acaso, você sabe como reconectar o hardware Bluetooth que foi desconectado usando Disable/Enable-NetAdapter? superuser.com/questions/1444278/…
JinSnow em
3

Esse script de Autohotkey parece fazer o truque. Estou incomodado com o que está Sleeplá, mas parece que a janela fica ativa antes de estar pronta para receber minhas teclas.

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

Transposto para /programming//q/48700268/308851 para descobrir com o que isso Sleep 300poderia ser substituído.

chx
fonte
Isso também pode ser uma solução na maioria dos casos. Eu também precisava dormir um pouco depois de pressionar as teclas. E esta solução não funciona se a tela estiver bloqueada. O aplicativo Universal do Windows que eu postei acima funciona mesmo com a tela bloqueada.
Martin Pecka
2

Aqui está uma solução parcial: wmic path Win32_PNPEntity where "caption like '%bluetooth%' AND DeviceID like 'USB\\%'" call disablecertamente faz com que a chave liga / desliga do Bluetooth desapareça e o Gerenciador de dispositivos reporte This device is disabled. (Code 22). Se isso é suficiente para matar o rádio, não tenho certeza.

Não consigo encontrar documentação sobre quais argumentos callaceitam. Eu acho que deveria haver algum tipo de rfkillaqui.

chx
fonte
Sinto muito, não funciona para mim como você o descreve. Para mim, a reprodução do Bluetooth é interrompida, mas todos os botões do Bluetooth no painel de controle permanecem ativados. E ligar com enablenão retoma a reprodução do Bluetooth. A documentação da classe PNPEntity está aqui: msdn.microsoft.com/en-us/library/aa394353(v=vs.85).aspx , mas nenhum outro método útil parece estar lá ...
Martin Pecka,
1

Você pode usar o DevManView para ativar / desativar um dispositivo na linha de comando usando esta sintaxe:

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

Também permite o uso de curingas com o /use_wildcardargumento

rahuldottech
fonte
O Devmanview é realmente uma ferramenta útil, mas não resolve o meu problema. O problema é que não parece haver um dispositivo que você possa desativar no gerenciador de dispositivos para desligar o rádio bluetooth.
Martin Pecka
@MartinPecka Você não vê nada disso? i.stack.imgur.com/UrOuc.png Se não, você pode querer experimentar e atualizar os drivers ...
rahuldottech
Eu vejo o dispositivo Bluetooth, mas desativá-lo não interrompe a reprodução - provavelmente porque o sistema precisa ser reiniciado para que ele realmente fique desativado (conforme indicado na pergunta original).
Martin Pecka
0

O Powershell possui cmdlets para fazer exatamente o que você está procurando:

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

Use Get-Device para obter uma lista dos dispositivos. Você pode canalizar isso através do objeto where para selecionar seu dispositivo e, em seguida, canalizar para Disable-Device ou Enable-Device.

Instruções detalhadas...

Baixe e descompacte o arquivo.

Inicie um PowerShell como administrador.

Altere a política de execução, se necessário:

Set-ExecutionPolicy Unrestricted

Importe o módulo:

Import-Module .\DeviceManagement.psd1

Se você precisar restringir a lista de dispositivos, poderá usar uma comparação semelhante:

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

Se você souber o nome exato, poderá usar uma comparação -eq (igual):

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

Limpe as mãos nas calças.

apocalipse
fonte
Isso desativará o dispositivo USB em vez de apenas o rádio. wmicpode fazer isso também, pelo menos acho que sim.
CHX
A pergunta não perguntou como desativar o rádio, mas não o adaptador. Por que a distinção? Se você puder me dar uma boa razão, considerarei procurar por você, mas respondi à pergunta "O que realmente me interessa é realmente uma maneira de desativar / ativar o adaptador Bluetooth." - Martin Pecka 9:31 "
apocalysque
Sinto muito, qual é a diferença entre adaptador e rádio? Eu considero esses dois termos equivalentes. Existe uma carga de dispositivos de software que essa coisa de HW fornece, e você está certo de que esta pergunta não é sobre eles.
Martin Pecka
Além disso, este e o script PS de 2012 de Ricardo Mendes não funcionam no meu Win 10 1709 64bit, como é mencionado em seus comentários. Ambos acabam com erro Disable-Device : Error calling SetupDiCallClassInstaller. Eu os executo como administrador e com política de execução irrestrita.
Martin Pecka
0

Criei um script em lote que verifica um valor de chave reg que só estaria em vigor se o seu rádio bluetooth estivesse ativado. Em seguida, chama o script powershell de Ben N acima com o parâmetro correto para mudar seu estado atual. Transforma em um atalho de alternância, em vez de precisar ativar e desativar separadamente.

@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
007craft
fonte
-1

A execução do seguinte comando no prompt de comando (como administrador) fez o truque:

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

Eu já havia usado o mesmo comando para desativar meu adaptador Wi-Fi e descobri que ele também funcionava com os outros adaptadores em: Painel de controle> Rede e Internet> Conexões de rede. Apenas mude o argumento "name" para o nome do seu adaptador. Você também pode habilitá-lo novamente alterando o último argumento para admin=enabled.

Micah Vertal
fonte
1
Isso também parece apenas desativar os drivers PAN, mas não desliga o próprio dispositivo de rádio (no painel de controle, o Bluetooth ainda está sendo relatado como "ativado").
Martin Pecka
Verificado agora pelo bluetooth repro test, não desliga o bluetooth.
Martin Pecka
Me desculpe @ peci1, eu entendi sua pergunta. Eu já tinha consultado questões relacionadas à desativação do Bluetooth e interpretado sua pergunta da mesma forma. Então, seu objetivo é desligar (cortar a energia) o dispositivo Bluetooth? Vou pesquisar um pouco e informar se encontrar alguma coisa.
Micah Vertal 07/07
@ peci1 esse link seria útil?
Micah Vertal
Não, não tem. É sobre USB, não sobre dispositivos Bluetooth. E o Cmdlet de gerenciamento de dispositivos vinculado também não funciona.
Martin Pecka