Created
September 3, 2023 12:56
-
-
Save Lilleengen/e746ac3e6b563fb88139871af997017f to your computer and use it in GitHub Desktop.
Powershell script that gives you a systray icon to enble or disable bluetooth devices on Windows. Helps provent Windows from interfering with other devices using headphones.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$allBluetoothDevices = Get-PnpDevice -Class Bluetooth | |
$devicesByContainerId = @{} | |
foreach ($device in $allBluetoothDevices) { | |
$deviceProperties = Get-PnpDeviceProperty -InstanceId $device.InstanceId | |
$containerId = $deviceProperties | Where-Object { $_.KeyName -eq "DEVPKEY_Device_ContainerId" } | Select -ExpandProperty "Data" | |
if (-Not ($devicesByContainerId[$containerId])) { | |
$devicesByContainerId.add($containerId, @()) | |
} | |
$devicesByContainerId[$containerId] += $device.InstanceId | |
} | |
$nameByContainerId = @{} | |
foreach($containerId in $devicesByContainerId.keys) { | |
$names = @() | |
foreach($instanceId in $devicesByContainerId[$containerId]) { | |
$names += $allBluetoothDevices | Where-Object { $_.InstanceId -eq $instanceId } | Select -ExpandProperty "FriendlyName" | |
} | |
$shortestName = $names | Sort-Object Length | Select -First 1 | |
$nameByContainerId.add($containerId, $shortestName) | |
} | |
$statusByContainerId = @{} | |
foreach($containerId in $devicesByContainerId.keys) { | |
$firstInstanceId = $devicesByContainerId[$containerId][0] | |
$status = $allBluetoothDevices | Where-Object { $_.InstanceId -eq $firstInstanceId } | Select -ExpandProperty "Status" | |
$statusByContainerId.add($containerId, $status) | |
} | |
[System.Reflection.Assembly]::LoadWithPartialName('System.Drawing') | out-null | |
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | out-null | |
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("C:\Windows\System32\fsquirt.exe") | |
# Add the systray icon | |
$Main_Tool_Icon = New-Object System.Windows.Forms.NotifyIcon | |
$Main_Tool_Icon.Text = "Disable bluetooth devices" | |
$Main_Tool_Icon.Icon = $icon | |
$Main_Tool_Icon.Visible = $true | |
$menuItems = @() | |
$enableDisable = @{} | |
$order = [string[]] $devicesByContainerId.keys | |
foreach($containerId in $order) { | |
$menuItem = New-Object System.Windows.Forms.MenuItem | |
$enableDisable.add($containerId, $menuItem) | |
$isEnabled = $statusByContainerId[$containerId] -eq "OK" | |
$index = $order.IndexOf($containerId) | |
$enableDisable[$containerId].Index = $index | |
if ($isEnabled) { | |
$enableDisable[$containerId].Text = $nameByContainerId[$containerId] | |
} else { | |
$enableDisable[$containerId].Text = "[DISABLED] " + $nameByContainerId[$containerId] | |
} | |
$menuItems += $enableDisable[$containerId] | |
$enableDisable[$containerId].add_Click({ | |
param ( | |
[object] $sender, | |
[System.EventArgs] $e | |
) | |
process { | |
$id = $order[$sender.Index] | |
$isEnabled = $statusByContainerId[$id] -eq "OK" | |
if ($isEnabled) { | |
foreach($instanceId in $devicesByContainerId[$id]) { | |
Disable-PnpDevice -InstanceId $instanceId -Confirm:$false | |
} | |
$enableDisable[$id].Text = "[DISABLED] " + $nameByContainerId[$id] | |
$statusByContainerId[$id] = "Error" | |
} else { | |
foreach($instanceId in $devicesByContainerId[$id]) { | |
Enable-PnpDevice -InstanceId $instanceId -Confirm:$false | |
} | |
$enableDisable[$id].Text = $nameByContainerId[$id] | |
$statusByContainerId[$id] = "OK" | |
} | |
} | |
}) | |
} | |
# Add menu exit | |
$Menu_Exit = New-Object System.Windows.Forms.MenuItem | |
$Menu_Exit.Text = "Exit" | |
$menuItems += $Menu_Exit | |
# Add all menus as context menus | |
$contextmenu = New-Object System.Windows.Forms.ContextMenu | |
$Main_Tool_Icon.ContextMenu = $contextmenu | |
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($menuItems) | |
$Menu_Exit.add_Click({ | |
$Main_Tool_Icon.Visible = $false | |
$window.Close() | |
Stop-Process $pid | |
}) | |
# Make PowerShell Disappear | |
$windowcode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' | |
$asyncwindow = Add-Type -MemberDefinition $windowcode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru | |
$null = $asyncwindow::ShowWindowAsync((Get-Process -PID $pid).MainWindowHandle, 0) | |
# Force garbage collection just to start slightly lower RAM usage. | |
[System.GC]::Collect() | |
$appContext = New-Object System.Windows.Forms.ApplicationContext | |
[void][System.Windows.Forms.Application]::Run($appContext) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment