Вопрос или проблема
Есть ли способ с помощью PowerShell или других инструментов подключать и отключать спаренное Bluetooth устройство? В основном, нажимать кнопку Подключить/Отключить в Bluetooth и других устройствах, но через командную строку любого вида (PowerShell, bat с использованием инструментов командной строки, код на C#, C++ и т.д.):
Я нашел этот ответ, но он включает в себя отключение и повторное спаривание, что не сработает, потому что мои наушники должны быть в режиме спаривания, чтобы принять новое спаривание. Я бы предпочел не симулировать нажатия клавиш и щелчки мыши с помощью AutoIt или другого такого программного обеспечения.
Я написал код на C++ для этого, используя Win32 Bluetooth API’s BluetoothSetServiceState
, но на самом деле достаточно использовать Bluetooth Command Line Tools.
Как оказалось, как только все службы, используемые устройством, отключены, устройство автоматически освобождается и disconnect’ится Windows. В моем случае это голос и музыка, согласно скриншоту, и большинство наушников будут работать так же.
Голос на самом деле представляет собой сервис Hands-Free (HFP), а музыка – это просто аудиопоток (A2DP). Идентификаторы услуг будут необходимы, и их можно определить с помощью команды btdiscovery
из указанного пакета или через список Bluetooth-услуг. Голос HFP – это 111e
, музыка A2DP – это 110b
.
Согласно справке по команде btcom
:
Использование:
btcom {-c|-r} {-bBluetoothAddress | -nFriendlyName} [-s{sp|dun|GUID|UUID}] -c Создать ассоциацию между COM-портом и удаленной службой (Включить не-COM службу). -r Удалить ассоциацию между COM-портом и удаленной службой (Отключить не-COM службу). -s Удаленная служба для использования (по умолчанию - служба последовательного порта) -b Bluetooth адрес удаленного устройства в формате (XX:XX:XX:XX:XX:XX). -n Дружественное имя удаленного устройства.
Чтобы отключить устройство, выполните следующее (работает только при запуске от имени администратора в моем случае, с использованием Windows 10 1809 (17763.437)):
"C:\Program Files (x86)\Bluetooth Command Line Tools\bin\btcom" -n "WH-1000XM3" -r -s111e
"C:\Program Files (x86)\Bluetooth Command Line Tools\bin\btcom" -n "WH-1000XM3" -r -s110b
Чтобы подключить снова, выполните то же самое с -c
вместо -r
. Это работает и для других устройств, не только для наушников, пока все службы/профили, к которым подключается Windows, отключены/включены.
Примечание: использование -n <дружественное имя>
гораздо медленнее по сравнению с использованием -b <адрес>
из-за выполнения обнаружения Bluetooth.
сочетания клавиш win 10 https://www.windowscentral.com/best-windows-10-keyboard-shortcuts
win-клавиша + K открывает боковое меню и тут же ищет Bluetooth-устройства.
затем щелкните по вашему уже спаренному устройству и подключите его.
Если решение от @MarcinJ с Bluetooth Command Line Tools для вас слишком медленное, особенно если вы хотите спарить устройство во время входящего звонка, попробуйте создать ярлык Windows:
(Кликните правой кнопкой мыши > Новый > Ярлык)
%windir%\explorer.exe ms-settings-connectabledevices:devicediscovery
Это отобразит панель отображения и аудио прямо на экране, которая на расстоянии одного клика от подключения.
И красивую иконку BT для ярлыка можно найти, например, в C:\Windows\System32\fsquirt.exe
.
Возможно, Get-PnPDevice
, Disable-PnPDevice
и Enable-PnPDevice
решат вашу задачу. Я не смог протестировать это, однако.
Пример:
$DeviceName = "YourDevice"
$BTDevice = Get-PnpDevice | Where-Object {$_.FriendlyName -eq $DeviceName -and $_.class -eq "Bluetooth"}
Disable-PnpDevice -InstanceId $BTDevice.DeviceID -Confirm:$false
Enable-PnpDevice -InstanceId $BTDevice.DeviceID -Confirm:$false
Измените переменную $DeviceName
на имя вашего BT устройства.
Используя вдохновение из https://github.com/stanleyguevara/win10-bluetooth-headphones, я доработал этот скрипт, чтобы я мог подключать/отключать несколько устройств одним кликом ярлыка (или сочетанием клавиш, привязанным к ярлыку).
Мой форк здесь: https://github.com/nickboldt/win10-bluetooth-headphones
Скрипт AutoHotkey, предложенный Павлом, очень вдохновляющий, но компиляция требует AutoHotkey. Я перенес код на PowerShell, чтобы код не требовал AutoHotkey:
Param(
[Parameter(Mandatory=$False,Position=1)]
[string]$dnp
)
if($dnp -eq "/?") {
Write-Host "использование: $($MyInvocation.InvocationName) [имя устройства]"
exit
}
if(!$dnp) {
$dnp="WH-1000XM4"
}
$devices = Get-ChildItem -Path HKLM:\SYSTEM\ControlSet001\Services\BTHPORT\Parameters\Devices
foreach($device in $devices) {
$address=$device.pschildname.ToUpper()
$name=$device.GetValue("Name")
if($name -ne $null) {
$printableName = ($name -notmatch 0 | ForEach{[char]$_}) -join ""
if($printableName -eq $dnp) {
$ma=$address
}
}
}
$gui="1"
if(!$ma) {
Write-Host "Устройство $dnp не найдено.`r`nОстановка."
if($gui -eq "1") {[System.Windows.Forms.MessageBox]::Show("Устройство $dnp не найдено.","Ошибка")}
exit
}
Write-Verbose "Работа с устройством $dnp и адресом $ma."
$id=get-random
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct BLUETOOTH_DEVICE_INFO$id {
public UInt32 dwSize;
public UInt64 Address;
public UInt64 ulClassofDevice;
public bool fConnected;
public bool fRemembered;
public bool fAuthenticated;
public decimal stLastSeen; //decimal такой же длинный, как SystemTime
public decimal stLastUsed; //decimal такой же длинный, как SystemTime
public string szName;
}
namespace bluco {
public class Program$id {
[DllImport("bthprops.cpl", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint BluetoothSetServiceState(IntPtr hRadio, ref BLUETOOTH_DEVICE_INFO$id DeviceInfo, ref Guid guid, int ServiceFlags);
public static void Main() {
BLUETOOTH_DEVICE_INFO$id mdi = new BLUETOOTH_DEVICE_INFO$id {
// ошибка 0x424, 1060 возникает, если нижеуказанный адрес неверен, это число, похоже, указывает на ERROR_SERVICE_DOES_NOT_EXIST
Address = Convert.ToUInt64("$ma", 16),
szName = "WH-1000XM5",
// 72 - это размер BLUETOOTH_DEVICE_INFO$id без строки szName
// согласно спецификации, строка szName имеет максимум 248 wchars
dwSize = (uint) (72 + 4*248)
};
Guid mUUID = new Guid("0000111e-0000-1000-8000-00805f9b34fb"); // https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/
uint hr0 = BluetoothSetServiceState(IntPtr.Zero, ref mdi, ref mUUID, 1);
mUUID = new Guid("0000110b-0000-1000-8000-00805f9b34fb"); // https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/
uint hr1 = BluetoothSetServiceState(IntPtr.Zero, ref mdi, ref mUUID, 1);
if(hr0 == 0 && hr1 == 0) {
Console.WriteLine("Bluetooth подключен.");
#pragma warning disable 162
if("$gui"=="1") System.Windows.Forms.MessageBox.Show("Bluetooth подключен.","Подключить");
#pragma warning restore 162
}
if(hr0 != 0 || hr1 != 0) {
mUUID = new Guid("0000111e-0000-1000-8000-00805f9b34fb");
hr0 = BluetoothSetServiceState(IntPtr.Zero, ref mdi, ref mUUID, 0);
// ошибка 0x424, 1060 возникает, если нижеуказанный адрес неверен, это число, похоже, указывает на ERROR_SERVICE_DOES_NOT_EXIST
mUUID = new Guid("0000110b-0000-1000-8000-00805f9b34fb");
hr1 = BluetoothSetServiceState(IntPtr.Zero, ref mdi, ref mUUID, 0);
if(hr0 == 0 && hr1 == 0) {
Console.WriteLine("Bluetooth отключен.");
#pragma warning disable 162
if("$gui"=="1") System.Windows.Forms.MessageBox.Show("Bluetooth отключен.","Отключить");
#pragma warning restore 162
}
}
}
}
}
"@ -Language CSharp -ReferencedAssemblies System.Windows.Forms
iex "[bluco.Program$id]::Main()"
Теперь я могу включать и выключать свои Bluetooth наушники из командной строки, используя PowerShell.
https://github.com/m2jean/ToothTray – это проект, реализующий подключение/отключение с Bluetooth аудио устройствами. Из его README.md:
Вместо использования API Bluetooth Windows, нужно использовать Windows Core Audio API для подключения Bluetooth аудио. В конечном итоге это драйвер подключает Bluetooth устройство к аудиосистеме Windows, и нам нужно получить интерфейс к Bluetooth аудио драйверу.
После того, как Bluetooth аудио устройства будут спарены и драйвера установлены, они появятся в Windows как аудио точки, которые можно перечислить с помощью EnumAudioEndpoints. Каждая точка имеет различные свойства. Их доступность зависит от типа точки. Мы можем перечислить свойства программно или просмотреть их на вкладке “Сведения” устройства в Диспетчере устройств.
Одно полезное свойство – это
state
точки, которое говорит нам, подключено ли Bluetooth аудио устройство. Если оно подключено, состояние будетDEVICE_STATE_ACTIVE
. В противном случае оно будетDEVICE_STATE_UNPLUGGED
.После получения точек мы должны использовать API топологии устройств, чтобы получить интерфейс к драйверу. В модели драйвера Windows (WDM) драйвера выставляют оборудование и свою функциональность с помощью графа компонентов ядрового стриминга (KS). Путем навигации через топологию мы можем найти компоненты KS, которые фактически контролируют подключение Bluetooth аудио устройства.
И оказывается, что компонент KS, который мы ищем, всегда является фильтром KS, непосредственно подключенным к аудиоточке (что могло быть указано в соответствующих документах по разработке драйвера WDM). Мы можем получить фильтр, получив соединитель фильтра от соединителя точки. Затем мы можем использовать интерфейс
IKsControl
фильтра, чтобы отправить запрос свойстваKSPROPSETID_BtAudio
драйверу, который аналогичен запросам IO. Отправляя либоKSPROPERTY_ONESHOT_RECONNECT
, либоKSPROPERTY_ONESHOT_DISCONNECT
, мы просим драйвер подключиться или отключиться от Bluetooth аудио устройства.
Подробная реализация доступна в его коде.
Я форкнул его и сделал его основные функции в CLI-версии для использования в сценариях: https://github.com/shunf4/ToothTrayCli
Обратите внимание, что вышеуказанное относится только к Bluetooth аудио устройствам.
Отредактировано на основе ответа OP.
Смотрим на подлежащий класс, этот элемент не доступен для программного доступа.
Когда будет реализовано Close/Disconnect?
[Windows.Devices.Bluetooth.BluetoothDevice]Когда будет реализовано Close/Disconnect? Планируете ли вы иметь отключение? Dispose() не закрывает соединение
849 открыто 9 января 2019 года
Не похоже, что существует другой API документ, который говорит обратное. Так что, похоже, вы застряли с SendKeys, AutoIT и т.д., по крайней мере, на данный момент.
Довольно старый пост, но я недавно нашел способ сделать это без дополнительных сторонних инструментов.
Кратко:
В Windows 11 перейдите в Настройки > Система > Для разработчиков и включите Режим разработчика, Портал устройства и Ограничить только для циклических подключений. Отключите Аутентификацию. Перейдите на http://localhost:50080/#Bluetooth, чтобы найти ID вашего уже спаренного Bluetooth устройства; преобразуйте его в base64. Затем следующая команда будет работать из командной строки:
curl -d "" http://localhost:50080/api/bt/connectdevice?deviceId={ID_in_base64}
Длинная версия:
Это решение использует возможности Портала устройства Windows, который позволяет вам администрировать свой ПК через веб-запросы. Узнайте больше о том, что он может делать здесь. Перейдите в Настройки > Система > Для разработчиков и включите Режим разработчика, затем включите Портал устройства. Это вызовет установку Пакета режима разработчика, что может занять несколько минут и может потребовать перезагрузки. Как только он будет включен, включите Ограничить только для циклических подключений. Это очень важно по соображениям безопасности; это означает, что вы сможете получить доступ к Порталу устройства только с вашего локального ПК. В противном случае любой, кто в той же сети, сможет прочитать все файлы на вашем ПК. Как только вы это сделаете, вы можете безопасно отключить Аутентификацию. В качестве альтернативы, вы можете оставить Аутентификацию включенной, но имейте в виду, что вам придется указать имя пользователя и пароль в открытом виде в ваших веб-запросах позже.
Как только это сделано, вы увидите URL для Портала устройства, который должен выглядеть как http://localhost:50080, хотя номер порта может быть другим. Перейдите по этому URL, и вы увидите Портал устройства; выберите Bluetooth в боковом меню, чтобы увидеть ваши Bluetooth устройства. Предполагая, что ваше Bluetooth устройство уже спарено, вы увидите его в списке, даже если оно в данный момент отключено. Скопируйте полный ID вашего Bluetooth устройства и преобразуйте его в base64 с помощью сайта, такого как https://base64.guru/converter.
Наконец, вы можете использовать REST API, чтобы подключить или отключить ваше Bluetooth устройство. Самый простой способ – использовать curl, который по умолчанию установлен в Windows в наши дни. Но вы также можете использовать пакет requests в Python, если хотите сделать что-то еще более изысканное. URL-адреса для подключения или отключения вашего устройства следующие:
http://localhost:50080/api/bt/connectdevice?deviceId={ID_in_base64}
http://localhost:50080/api/bt/disconnectdevice?deviceId={ID_in_base64}
Чтобы использовать curl, включите флаг -d
с пустыми кавычками (что устанавливает Длину содержимого равной 0), затем URL, вот так: curl -d "" {url}
Я успешно протестировал следующий vbs-скрипт в Windows 10. Здесь я симулирую нажатия клавиш, используя команду SendKeys
. Количество {TAB}
будет отличаться на вашей системе, чтобы достичь имени Bluetooth устройства.
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "ms-settings:bluetooth"
WScript.Sleep 2500
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{ENTER}"
WScript.Sleep 500 '
WshShell.SendKeys "{TAB}"
WScript.Sleep 500 '
WshShell.SendKeys "{ENTER}"
Ответ или решение
Чтобы подключить или отключить сопряжённое Bluetooth-устройство с помощью скриптов, можно использовать несколько подходов. Этот процесс может быть реализован с помощью PowerShell, C#, и других инструментов. Ниже приводится подробное описание нескольких методов:
1. Использование Bluetooth Command Line Tools
Существует набор инструментов командной строки для работы с Bluetooth на Windows, известный как Bluetooth Command Line Tools. Он позволяет подключать и отключать Bluetooth-устройства, не требуется повторное сопряжение.
Команды для отключения устройства:
"C:\Program Files (x86)\Bluetooth Command Line Tools\bin\btcom" -n "Ваше_Устройство" -r -s111e
"C:\Program Files (x86)\Bluetooth Command Line Tools\bin\btcom" -n "Ваше_Устройство" -r -s110b
Эти команды отключают сервисы HFP (Voice) и A2DP (Music) для устройства. Не забудьте заменить "Ваше_Устройство"
на ваше реальное имя устройства.
Команды для подключения устройства:
"C:\Program Files (x86)\Bluetooth Command Line Tools\bin\btcom" -n "Ваше_Устройство" -c -s111e
"C:\Program Files (x86)\Bluetooth Command Line Tools\bin\btcom" -n "Ваше_Устройство" -c -s110b
2. Использование PowerShell
Другой подход — использование PowerShell для управления Bluetooth-устройствами:
$DeviceName = "Ваше_Устройство"
$BTDevice = Get-PnpDevice | Where-Object {$_.FriendlyName -eq $DeviceName -and $_.class -eq "Bluetooth"}
Disable-PnpDevice -InstanceId $BTDevice.DeviceID -Confirm:$false
Enable-PnpDevice -InstanceId $BTDevice.DeviceID -Confirm:$false
Этот скрипт сначала отключает, а затем включает устройство. Параметр $DeviceName
следует заменить на имя вашего устройства.
3. Использование C
Можно использовать Win32 Bluetooth API для управления Bluetooth-устройствами. Например:
using System;
using System.Runtime.InteropServices;
public class BluetoothManager
{
[DllImport("bthprops.cpl", SetLastError = true)]
public static extern uint BluetoothSetServiceState(IntPtr hRadio, ref BLUETOOTH_DEVICE_INFO deviceInfo, ref Guid guid, int serviceFlags);
public static void ToggleBluetoothDevice(string address, bool connect)
{
Guid serviceUUID = connect ? new Guid("0000111e-0000-1000-8000-00805f9b34fb") : new Guid("0000110b-0000-1000-8000-00805f9b34fb");
BLUETOOTH_DEVICE_INFO deviceInfo = new BLUETOOTH_DEVICE_INFO { Address = Convert.ToUInt64(address, 16) };
uint result = BluetoothSetServiceState(IntPtr.Zero, ref deviceInfo, ref serviceUUID, connect ? 1 : 0);
if (result == 0)
{
Console.WriteLine(connect ? "Устройство подключено." : "Устройство отключено.");
}
}
}
Замените address
на фактический адрес Bluetooth-устройства.
4. Использование Device Portal на Windows 11
Если у вас Windows 11, вы можете включить Device Portal для управления Bluetooth-устройствами через HTTP-запросы.
После включения Device Portal вы можете использовать curl
для подключения или отключения:
curl -d "" http://localhost:50080/api/bt/connectdevice?deviceId={ID_в_base64}
Для отключения:
curl -d "" http://localhost:50080/api/bt/disconnectdevice?deviceId={ID_в_base64}
Заключение
Все описанные методы имеют свои особенности и могут быть выбраны в зависимости от ситуации. Использование командной строки и PowerShell обеспечивает высокую гибкость и может быть внедрено в автоматизированные скрипты и процессы. Если же вы предпочитаете программный подход, тогда C# сценарий будет более подходящим.