4

I would like to emulated with a shortcut the process of 1) opening the Action Center and 2) clicking on the bluetooth icon.

My solution was to use AHK to map a keyboard shortcut to running a .bat, which contains the script suggested in this question.

But the suggested service doesn't activate/remove the magic little blue icon of the bluetooth in the tray bar.enter image description here

I have look for all bluetooth services that are turned on when I click on the bluetooth icon in action center and I have activated them via the suggested .bat, but still it's not working.

BluetoothUserService_182d916
bthserv
BthHFSrv  
BthHFEnum  
BthEnum   
BthHFAud
BthEnum
BthA2dp
Microsoft_Bluetooth_AvrcpTransport

Here are all the services: enter image description here enter image description here

My script (where I have replace Microsoft_Bluetooth_AvrcpTransport by all the service mentionned above):

@echo off

for /F "tokens=3 delims=: " %%H in ('sc query "Microsoft_Bluetooth_AvrcpTransport" ^| findstr "STATE"') do (
  if /I "%%H" NEQ "RUNNING" (
   net start "Microsoft_Bluetooth_AvrcpTransport"
  ) else if /I "%%H" NEQ "STOPPED" (
   net stop "Microsoft_Bluetooth_AvrcpTransport"
  )
)

@pause
2

3 Answers 3

3

First create an .ahk shortcut that starts a powershell:

#b::
Run, C:\Users\user\Desktop\bluetooth.ps1,,Hide 
return

Then you create a powershell:

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
if ($bluetooth.state -eq 'On') {$BluetoothStatus = 'Off'} else {$BluetoothStatus = 'On'}
Await ($bluetooth.SetStateAsync($BluetoothStatus)) ([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null

All credit goes to @Ben N and @Scott Heath


This script works when I launch it from VScode, when I copy-paste it in a powershell, or when I use a cmd to start it. But not when I double-click it or when I start it in .ahk. The work around was to create a .bat file with this

Run, C:\Users\user\Desktop\bluetooth.ps1,,Hide

And then call this .bat in ahk.

2
  • 1
    If the quoted powershell script doesn't work, as it didn't in my case, remove ` | Out-Null` from the final line and re-run, if it prints DeniedByUser then search for "Radio Privacy Settings" in start menu and allow apps to control radios.
    – Liam Lime
    Jun 17, 2021 at 20:24
  • 1
    For me the command in the bat looked like this: powershell.exe -ExecutionPolicy Bypass -File bluetooth.ps1
    – rokdd
    Feb 9, 2023 at 12:23
2

AutoHotkey v2.0 introduces a new syntax that replaces statements with functions, so the accepted answer is no longer a copy-and-paste solution.

To pull this off with AutoHotkey v2.0 on Windows 10.0.19045, I needed to create:

  1. toggle-bluetooth.ahk
#b::
{
    Run( 'C:\Users\<user>\Documents\AutoHotkey\toggle-bluetooth.bat', , 'Hide' )
    return
}

(The signature #b:: assigns hotkey Win+B to this function. See the AHK docs for details on notation.)

  1. toggle-bluetooth.bat
powershell.exe -ExecutionPolicy Bypass -File toggle-bluetooth.ps1
  1. toggle-bluetooth.ps1
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
if ($bluetooth.state -eq 'On') {$BluetoothStatus = 'Off'} else {$BluetoothStatus = 'On'}
Await ($bluetooth.SetStateAsync($BluetoothStatus)) ([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null

It's very possible that using the .bat as a middleman is not necessary with some other approach. But this is the only thing that I could get to work.

Obvious thanks to @MagTun and @rokdd for developing this solution.

0

You don't need to stop/start these services for getting rid of the Bluetooth traybar icon.

The display of the icon is controlled in the registry key HKEY_CURRENT_USER\Control Panel\Bluetooth, by the DWORD value Notification Area Icon whose value is 0 for Off and 1 for On. This requires restarting Explorer to take effect.

The following two .bat files will do the job.

Disable the Bluetooth notification area icon

REG ADD "HKCU\Control Panel\Bluetooth" /V "Notification Area Icon" /T REG_DWORD /D 00000000 /F
taskkill /f /im explorer.exe
start explorer.exe

Enable the Bluetooth notification area icon

REG ADD "HKCU\Control Panel\Bluetooth" /V "Notification Area Icon" /T REG_DWORD /D 00000001 /F
taskkill /f /im explorer.exe
start explorer.exe
8
  • Sorry I was clear enough, I do not want to get rid of the blue bluetooth icon, I want to start /stop the bluetooth, and when the bluetooth is on I want the blue icon, and when the bluetooth is stopped (and only then) I do not want the blue icon.
    – MagTun
    Oct 21, 2019 at 16:01
  • What was wrong with the post in a comment above?
    – harrymc
    Oct 21, 2019 at 18:29
  • The answer in the post works but I have some difficulties to adapt it so I can use it with a shortcut : superuser.com/questions/1494499
    – MagTun
    Oct 22, 2019 at 5:10
  • If that script works, the AutoHotKey command can be improved as Run, powershell C:\path\to\bluetooth.ps1 On and another shortcut for Off.
    – harrymc
    Oct 22, 2019 at 9:15
  • Yes, I could do that (which I am already doing) but I would like to use just one shortcut.
    – MagTun
    Oct 22, 2019 at 16:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .