Włącz / wyłącz radio / adapter Bluetooth z cmd / powershell w Windows 10

28

Takie proste zadanie, można powiedzieć, i nie znalazłem satysfakcjonującego rozwiązania. Co próbowałem (z muzyką odtwarzaną przez głośnik podłączony do Bluetooth, aby naprawdę poznać stan radia):

  • używanie devcon jako administratora: devcon disable USB\VID_8087&PID_07DC&REV_0001(który jest HW ID mojego adaptera Bluetooth) ... wymaga ponownego uruchomienia do pracy ...
  • używanie PowerShell jako admin: Disable-NetAdapter "Bluetooth Network Connection 3"(co jest tłumaczeniem nazwy mojego adaptera Bluetooth) ... wyłącza sterownik PAN, ale głośnik Bluetooth kontynuuje odtwarzanie muzyki ...
  • używanie net jako admin: net stop bthserv... tak naprawdę nie wyłącza radia (głośnik BT kontynuuje odtwarzanie muzyki)
  • using .NET: Najbardziej odpowiednia strona w MSDN nie mówi ani słowa o włączaniu / wyłączaniu adaptera.
  • using explorer: ms-settings:bluetoothor explorer.exe %LocalAppData%\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Settings\cs-CZ\AAA_SettingsPagePCSystemBluetooth.settingcontent-ms... otwiera panel ustawień Bluetooth, ale nadal muszę kliknąć przełącznik

Nie mogę uwierzyć, że Microsoft byłby tak ignorantem, gdyby nie wydał takiego polecenia ...

Martin Pecka
źródło
Jak grasz muzykę?
harrymc
Korzystanie z Winampa :)
Martin Pecka
Czy zabicie Winampa zatrzymuje muzykę?
harrymc
Oczywiście, dlaczego tak nie byłoby? Ale nie chodzi o zatrzymanie odtwarzania muzyki, chodzi o sterowanie radiem BT.
Martin Pecka
1
@harrymc Proszę przeczytać pytanie. Odtwarzanie muzyki to tylko sposób na wykrycie, czy połączenie Bluetooth działa, czy nie. To, co naprawdę mnie interesuje, to sposób na wyłączenie / włączenie adaptera Bluetooth.
Martin Pecka,

Odpowiedzi:

21

Jest to trudne ze względu na niezbędną współpracę z WinRT, ale jest to możliwe w czystej 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

Aby go użyć, zapisz plik PS1, np bluetooth.ps1. Jeśli jeszcze tego nie zrobiłeś, postępuj zgodnie z instrukcjami w sekcji Włączanie skryptów wiki tagu PowerShell, aby włączyć wykonywanie skryptów w systemie. Następnie możesz uruchomić go z wiersza polecenia programu PowerShell w następujący sposób:

.\bluetooth.ps1 -BluetoothStatus On

Aby wyłączyć Bluetooth, przekaż Offzamiast.

Aby uruchomić go z pliku wsadowego:

powershell -command .\bluetooth.ps1 -BluetoothStatus On

Zastrzeżenie: Jeśli usługa wsparcia Bluetooth nie jest uruchomiona, skrypt próbuje ją uruchomić, ponieważ w przeciwnym razie WinRT nie zobaczy radia Bluetooth. Niestety usługi nie można uruchomić, jeśli skrypt nie działa jako administrator. Aby było to niepotrzebne, możesz zmienić typ uruchamiania tej usługi na automatyczny.

Teraz trochę wyjaśnienia. Pierwsze trzy wiersze określają parametry, które przyjmuje skrypt. Zanim zaczniemy na poważnie, upewnimy się, że usługa pomocy technicznej Bluetooth jest uruchomiona i uruchom ją, jeśli nie. Następnie ładujemy System.Runtime.WindowsRuntimezestaw, abyśmy mogli użyć WindowsRuntimeSystemExtensions.AsTaskmetody do konwersji zadań w stylu WinRT (których .NET / PowerShell nie rozumie) na .NET Task. Ta konkretna metoda ma mnóstwo różnych zestawów parametrów, które wydają się wyzwalać rozdzielczość przeciążenia PowerShell, więc w następnym wierszu otrzymujemy konkretny, który przyjmuje tylko wynikowe zadanie WinRT. Następnie definiujemy funkcję, której użyjemy kilka razy, aby wyodrębnić wynik odpowiedniego typu z asynchronicznego zadania WinRT. Po deklaracji tej funkcji ładujemy dwa niezbędne typy z metadanych WinRT. Pozostała część skryptu to właściwie tylko tłumaczenie PowerShell kodu C # napisanego w odpowiedzi; używa Radioklasy WinRT do wyszukiwania i konfigurowania radia Bluetooth.

Ben N.
źródło
1
Nie można wywołać metody dla wyrażenia o wartości zerowej. W C: \ Users \ chx \ AppData \ Local \ Microsoft \ WindowsApps \ bluetooth.ps1: 18 char: 1 + Oczekuj ($ bluetooth.SetStateAsync ($ BluetoothStatus)) ([
Urządzenia Windows
@chx Czy jesteś pewien, że twoje urządzenie ma adapter Bluetooth? Jeśli nie ma radia Bluetooth, linia od trzeciej do ostatniej zostanie ustawiona $bluetoothna zero, co spowoduje, że linia od ostatniej do ostatniej spowoduje wystąpienie tego błędu.
Ben N
Jestem w 100% pewien, że jest to widoczne w aplikacji „Ustawienia” i słucham muzyki bezprzewodowo, zarówno Menedżer urządzeń, jak i wmic również to zgłaszają.
chx
@chx Hmm, co otrzymasz, jeśli zamienisz ostatnie trzy wiersze na just $radios? To pokaże listę radiotelefonów, które zwrócił WinRT.
Ben N
2
Sprytnie, to działa! Po prostu nie mogłem skompilować aplikacji komputerowej przy użyciu tego interfejsu API, ale wydaje się, że to dynamiczne ładowanie w skrypcie. Teraz porównaj do rfkill unblock bluetoothLinuksa :-D
Martin Pecka
5

Po rezygnacji z poszukiwania gotowych rozwiązań dowiedziałem się, że aplikacje platformy Universal Windows mają dostęp do interfejsu API sterowania radiowego .

Połączyłem więc przykładową aplikację do sterowania radiowego z aplikacją sterowaną za pomocą wiersza poleceń, a wynik jest tutaj: https://github.com/peci1/RadioControl . Jest opublikowany w Windows Store .

Ogólnie rzecz biorąc, nie można po prostu pozwolić aplikacji działać w tle, więc najpierw musisz uruchomić GUI, a następnie możesz wywołać go z wiersza poleceń, np.

radiocontrol.exe 0 on
radiocontrol.exe Bluetooth off

Podstawowe funkcje tej aplikacji to:

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

Następnie musisz również dodać funkcję Radia do manifestu aplikacji:

<DeviceCapability Name="radios" />

Aby umożliwić kontrolę z wiersza poleceń, musisz przesłonić metodę protected override async void OnActivated(IActivatedEventArgs args)w App.xaml.cs i wykonać przetwarzanie w gałęzi takiej jak ta:

switch (args.Kind)
        {
            case ActivationKind.CommandLineLaunch:
Martin Pecka
źródło
Ta odpowiedź lepiej pasuje do StackOverflow.
harrymc
@MartinPecka Czy przypadkiem wiesz, jak ponownie podłączyć sprzęt Bluetooth, który został odłączony Disable/Enable-NetAdapter? superuser.com/questions/1444278/…
JinSnow
3

Ten skrypt Autohotkey wydaje się załatwić sprawę. Niepokoi mnie to Sleep, ale wydaje się, że okno staje się aktywne, zanim będzie gotowe na odbieranie moich naciśnięć klawiszy.

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

Przesłano na /programming//q/48700268/308851, aby dowiedzieć się, co Sleep 300można by zastąpić.

chx
źródło
W większości przypadków może to być również rozwiązanie. Musiałem także dodać krótki sen po wysłaniu naciśnięcia klawisza. To rozwiązanie nie działa, jeśli ekran jest zablokowany. Aplikacja Universal Windows, którą opublikowałem powyżej, działa nawet przy zablokowanym ekranie.
Martin Pecka,
2

Oto częściowe rozwiązanie: z wmic path Win32_PNPEntity where "caption like '%bluetooth%' AND DeviceID like 'USB\\%'" call disablepewnością powoduje zniknięcie przełącznika włączania / wyłączania Bluetooth i zgłasza Menedżer urządzeń This device is disabled. (Code 22). Czy to wystarczy, żeby zabić radio, nie jestem pewien.

Nie mogę znaleźć dokumentacji dotyczącej callakceptowanych argumentów . Myślę, że tutaj powinno być coś takiego rfkill.

chx
źródło
Przepraszam, nie działa dla mnie jak to opisujesz. Dla mnie odtwarzanie Bluetooth zatrzymuje się, ale wszystkie przełączniki Bluetooth w panelu sterowania pozostają włączone. A dzwonienie za pomocą enablenie wznawia odtwarzania Bluetooth. Dokumentacja dotycząca klasy PNPEntity znajduje się tutaj: msdn.microsoft.com/en-us/library/aa394353(v=vs.85).aspx , ale wydaje się, że nie ma innych przydatnych metod ...
Martin Pecka
1

Możesz użyć DevManView, aby włączyć / wyłączyć urządzenie z wiersza poleceń, używając następującej składni:

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

Pozwala także na użycie symboli wieloznacznych z /use_wildcardargumentem.

rahuldottech
źródło
Devmanview jest rzeczywiście przydatnym narzędziem, ale nie rozwiązuje mojego problemu. Problem polega na tym, że nie ma urządzenia, które można wyłączyć w menedżerze urządzeń, aby wyłączyć radio bluetooth.
Martin Pecka,
@MartinPecka Nie widzisz żadnego z nich? i.stack.imgur.com/UrOuc.png Jeśli nie, możesz spróbować zaktualizować sterowniki ...
rahuldottech
Widzę urządzenie Bluetooth, ale wyłączenie go nie zatrzymuje odtwarzania - prawdopodobnie dlatego, że system musi zostać zrestartowany, aby naprawdę został wyłączony (jak podano w pierwotnym pytaniu).
Martin Pecka
0

Powershell ma polecenia cmdlet do robienia dokładnie tego, czego szukasz:

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

Użyj Get-Device, aby uzyskać listę urządzeń. Możesz potokować to przez obiekt-miejsce, aby wybrać urządzenie, a następnie potokować to do Wyłącz urządzenie lub Włącz urządzenie.

Szczegółowe instrukcje...

Pobierz i rozpakuj plik.

Uruchom PowerShell jako administrator.

W razie potrzeby zmień zasady wykonywania:

Set-ExecutionPolicy Unrestricted

Zaimportuj moduł:

Import-Module .\DeviceManagement.psd1

Jeśli chcesz zawęzić listę urządzeń, możesz użyć porównania podobnego do:

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

Jeśli znasz dokładną nazwę, możesz użyć -eq (równa się):

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

Wytrzyj ręce w spodnie.

apokalipsa
źródło
Spowoduje to wyłączenie urządzenia USB zamiast tylko radia. wmicteż mogę to zrobić, przynajmniej tak mi się wydaje.
chx
Pytanie nie pytało, jak wyłączyć radio, ale nie adapter. Skąd to rozróżnienie? Jeśli możesz podać mi dobry powód, rozważę wykopanie dla ciebie, ale odpowiedziałem na pytanie: „Naprawdę interesuje mnie sposób na wyłączenie / włączenie adaptera Bluetooth. - Martin Pecka, 5 lutego o 9:31 "
apokalipsa
Przepraszam, jaka jest różnica między adapterem a radiem? Te dwa terminy uważam za równoważne. Jest *** mnóstwo urządzeń programowych, które zapewnia to oprogramowanie sprzętowe, i masz rację, to pytanie nie dotyczy ich.
Martin Pecka,
Co więcej, zarówno ten, jak i skrypt PS 2012 Ricarda Mendesa nie działają na moim Win 10 1709 64bit, jak wspomniano w ich komentarzach. Oba kończą się błędem Disable-Device : Error calling SetupDiCallClassInstaller. Prowadzę je jako administrator i z nieograniczoną polityką wykonywania.
Martin Pecka,
0

Zrobiłem skrypt wsadowy, który sprawdza wartość klucza reg, która byłaby dostępna tylko wtedy, gdy radio Bluetooth było włączone. Następnie wywołuje powyższy skrypt Powershell Ben N z poprawnym parametrem, aby przełączyć jego bieżący stan. Zmienia go w skrót przełączający, zamiast konieczności osobnego włączania i wyłączania.

@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
źródło
-1

Wykonanie następującego polecenia z wiersza polecenia (jako administrator) załatwiło sprawę:

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

Wcześniej użyłem tego samego polecenia, aby wyłączyć moją kartę Wi-Fi, i stwierdziłem, że działa ona również z innymi kartami w: Panel sterowania> Sieć i Internet> Połączenia sieciowe. Wystarczy zmienić argument „name” na nazwę adaptera. Możesz także włączyć go ponownie, zmieniając ostatni argument na admin=enabled.

Micheasz Vertal
źródło
1
Wydaje się to również wyłączać sterowniki PAN, ale nie wyłącza samego urządzenia radiowego (w panelu sterowania Bluetooth nadal jest zgłaszany jako „włączony”).
Martin Pecka,
Zweryfikowany teraz przez test repro bluetooth, nie wyłącza bluetooth.
Martin Pecka,
Przepraszam @ peci1, źle zrozumiałem twoje pytanie. Wcześniej patrzyłem na pytania związane z wyłączeniem Bluetooth i interpretowałem twoje pytanie tak samo. Czy Twoim celem jest wyłączenie (odcięcie zasilania) urządzenia Bluetooth? Zbadam trochę i dam ci znać, jeśli coś znajdę.
Micah Vertal
@ peci1 czy ten link byłby w ogóle pomocny?
Micah Vertal
Nie. Chodzi o USB, a nie urządzenia Bluetooth. Polecenie cmdlet zarządzania urządzeniami również nie działa.
Martin Pecka