23

Такая простая задача, можно сказать, и я не нашел удовлетворительного решения. Что я пробовал (с музыкой, воспроизводимой через Bluetooth-подключенный динамик, чтобы действительно знать состояние радио):

  • использование devcon в качестве администратора: devcon disable USB\VID_8087&PID_07DC&REV_0001 (это HW ID моего адаптера Bluetooth)... требуется перезагрузка для работы ...
  • использование powershell в качестве администратора: Disable-NetAdapter "Bluetooth Network Connection 3" (которое переводит название моего адаптера Bluetooth)... он отключает драйвер PAN, но динамик Bluetooth продолжает воспроизводить музыку ...
  • использование net как admin: net stop bthserv ... фактически не выключает радио (динамик BT продолжает воспроизводить музыку)
  • использование .NET: на самой релевантной странице MSDN не сказано ни слова о включении / выключении адаптера.
  • используя проводник: ms-settings:bluetooth или explorer.exe %LocalAppData%\Packages\windows.immersivecontrolpanel_cw5n1h2txyewy\LocalState\Indexed\Settings\cs-CZ\AAA_SettingsPagePCSystemBluetooth.settingcontent-ms ... открывает панель настроек Bluetooth, но у меня все еще есть нажать на переключатель

Я не могу поверить, что Microsoft так невежественна, чтобы не предоставлять такую команду ...

9 ответов9

12

Это сложно из-за необходимости взаимодействия с 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, чтобы включить выполнение сценариев в вашей системе. Затем вы можете запустить его из командной строки PowerShell следующим образом:

.\bluetooth.ps1 -BluetoothStatus On

Чтобы выключить Bluetooth, вместо этого передайте Off .

Чтобы запустить его из командного файла:

powershell -command .\bluetooth.ps1 -BluetoothStatus On

Предупреждение: если служба поддержки Bluetooth не запущена, сценарий пытается запустить ее, потому что в противном случае WinRT не увидит радио Bluetooth. Увы, сервис не может быть запущен, если скрипт не работает от имени администратора. Чтобы сделать это ненужным, вы можете изменить тип запуска этой службы на автоматический.

Теперь для некоторого объяснения. Первые три строки устанавливают параметры, которые принимает скрипт. Прежде чем начать всерьез, мы должны убедиться, что служба поддержки Bluetooth работает, и запустить ее, если нет. Затем мы загружаем System.Runtime.WindowsRuntime чтобы мы могли использовать WindowsRuntimeSystemExtensions.AsTask для преобразования задач в стиле WinRT (чего не понимает .NET/PowerShell) в .NET Task s. Этот конкретный метод имеет множество различных наборов параметров, которые, по-видимому, приводят к снижению разрешения перегрузки PowerShell, поэтому в следующей строке мы получим конкретный метод, который принимает только результативную задачу WinRT. Затем мы определяем функцию, которую будем использовать несколько раз, чтобы извлечь результат соответствующего типа из асинхронной задачи WinRT. После объявления этой функции мы загружаем два необходимых типа из метаданных WinRT. Остальная часть сценария в значительной степени является просто переводом PowerShell кода C #, который вы написали в своем ответе; он использует класс Radio WinRT для поиска и настройки радио Bluetooth.

3

Отказавшись от поиска готовых решений, я обнаружил, что приложения универсальной платформы Windows имеют доступ к API-интерфейсу радиоуправления.

Поэтому я объединил образец приложения для управления радио с приложением, управляемым из командной строки, и результат здесь: https://github.com/peci1/RadioControl . Он опубликован в Магазине Windows .

В общем случае невозможно просто запустить приложение в фоновом режиме, поэтому сначала нужно запустить графический интерфейс, а затем вызвать его из командной строки, например

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:
2

Этот скрипт 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 .

1

Вот частичное решение: wmic path Win32_PNPEntity where "caption like '%bluetooth%' AND DeviceID like 'USB\\%'" call disable безусловно, приводит к исчезновению переключателя Bluetooth On/Off и отчетов диспетчера This device is disabled. (Code 22) . Достаточно ли этого, чтобы убить радио, я не уверен.

Я не могу найти документацию о том, какие аргументы принимает call . Я думаю, что здесь должно быть что-то вроде rfkill .

0

В Powershell есть командлеты для выполнения именно того, что вы ищете:

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

Используйте Get-Device, чтобы получить список устройств. Вы можете передать это через where-object, чтобы выбрать ваше устройство, а затем передать это Disable-Device или Enable-Device.

Подробные инструкции ...

Загрузите и разархивируйте файл.

Запустите PowerShell как администратор.

Измените политику выполнения при необходимости:

Set-ExecutionPolicy Unrestricted

Импортируйте модуль:

Import-Module .\DeviceManagement.psd1

Если вам нужно сузить список устройств, вы можете использовать сравнение:

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

Если вы знаете точное имя, вы можете использовать -eq (равно) сравнить:

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

Протрите руки на штаны.

0

Вы можете использовать DevManView для включения / выключения устройства из командной строки, используя следующий синтаксис:

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

Это также позволяет использовать подстановочные знаки с аргументом /use_wildcard .

0

Я сделал пакетный скрипт, который проверяет значение ключа reg, которое будет доступно только в том случае, если ваше радио Bluetooth было включено. Затем он вызывает приведенный выше скрипт powershell от Ben N с правильным параметром для переключения его текущего состояния. Превращает его в ярлык переключения, вместо того, чтобы использовать его отдельно или выключать.

@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

Я думаю, что у меня есть ответ для вас, но мое корпоративное устройство Win10 заблокировано. Это должно быть изменение значения ключа реестра, поэтому запустите CMD от имени администратора и запросите ключ, затем используйте REG DELETE и ADD, чтобы изменить значение, которое должно отключить и включить службу.

Или вы можете написать обычный текстовый файл .reg, чтобы перезаписать значения ключей, но для выполнения потребуются права администратора.

Во всяком случае, я верю, что у вас есть навыки, чтобы разобраться с этим, как только найдете.

Удачи,

сойка

-1

Выполнение следующей команды из командной строки (как администратор) сделало свое дело:

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

Ранее я использовал ту же команду для отключения моего адаптера Wi-Fi и обнаружил, что она также работает с другими адаптерами в: Панель управления> Сеть и Интернет> Сетевые подключения. Просто измените аргумент "name" на имя вашего адаптера. Вы также можете включить его снова, изменив последний аргумент на admin=enabled .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .