Switch default audio devices (output + input) using profiles — keyboard shortcuts, a system tray icon, autostart. No external dependencies, no administrator rights required.
Same architecture as NetSetPS: a precompiled DLL instead of runtime Add-Type, a shortcut with -WindowStyle Minimized + HideConsole() inside the script, a NotifyIcon with a manual MouseUp handler.
powershell -ExecutionPolicy Bypass -File .\Install.ps1What it does:
- copies the scripts to
%LOCALAPPDATA%\AudioSwitchPS - compiles
AudioSwitchPS.Native.dll(csc.exefrom .NET Framework 4.x — present on every Windows install) - creates a Start Menu shortcut and a Startup shortcut
- launches the app
Switches: -NoAutostart, -NoLaunch, -Force (rebuild the DLL), -InstallPath.
Uninstall: .\Uninstall.ps1 [-RemoveConfig]
| Layer | Mechanism |
|---|---|
| Device list, volume, mute | IMMDeviceEnumerator / IAudioEndpointVolume (Core Audio API) |
| Changing the default device | IPolicyConfig::SetDefaultEndpoint — undocumented COM, the only way to do it without the GUI |
| Global hotkeys | RegisterHotKey + an invisible NativeWindow catching WM_HOTKEY |
| Autostart | a .lnk shortcut in shell:startup (per-user, no Task Scheduler, no UAC) |
Roles set on switch: eConsole + eMultimedia always, eCommunications when SetCommunicationsRole = true.
Toggling "Run at Windows startup" in the tray menu does not show a UAC prompt — creating a shortcut in the per-user Startup folder doesn't need elevation, so there's nothing to confirm. Feedback comes as a MessageBox confirming whether the shortcut was actually created/removed (an earlier version relied on a balloon tip, which Windows 10/11 frequently suppresses — Focus Assist, notification settings, or simply firing a second balloon too soon — making a successful toggle look like nothing happened).
To verify manually: open shell:startup (Win+R) and check for AudioSwitchPS.lnk, or check the log at %APPDATA%\AudioSwitchPS\audioswitchps.log for an Autostart enabled: / Autostart disabled. line.
%APPDATA%\AudioSwitchPS\audioprofiles.json — created on first run from the current devices. Full-field template: audioprofiles.example.json.
{
"Settings": { "SetCommunicationsRole": true, "ShowBalloon": true, "BalloonTimeoutMs": 1500 },
"Profiles": [
{
"Name": "Headset",
"Hotkey": "Ctrl+Alt+1",
"Output": { "Name": "*Jabra*", "Id": "{0.0.0.00000000}...", "Volume": 45, "Mute": false },
"Input": { "Name": "*Jabra*" }
}
]
}Output/Input— both sections optional (a profile can change output only).Volume(0–100) andMute— optional, skipped if the field is absent.- Device matching order:
Idfirst, thenNamewith a wildcard, then a name fragment. Worth keeping both —Idis fast and unambiguous,Namesaves the profile after a USB device is moved to a different port (which changes itsId).
Ctrl / Alt / Shift / Win + a key, e.g. Ctrl+Alt+1, Ctrl+Shift+F9, Win+Alt+Num1, Ctrl+Alt+Oemtilde.
A hotkey already in use elsewhere doesn't crash the app — you get a balloon listing the conflicts, and a WARN line in the log.
The tray menu and the "Save current as profile" dialog use a dark steel/slate palette (AudioSwitchPS.Native.DarkColorTable) with subtly rounded corners (ApplyRoundedCorners — DWM corner preference on Windows 11, a GDI region fallback on Windows 10). Disabled header lines (current output/input) use a dimmed but still legible gray rather than the renderer's default near-invisible disabled color. Standard MessageBox dialogs (autostart confirmation, "already running") stay OS-native and aren't restyled — theming those would require a custom owner-drawn dialog, which wasn't worth the added surface area here.
Current output/input · profile list (checkmark on the active one) · quick single-device selection with volume · Save current as profile · edit the JSON in Notepad with auto-reload on save · autostart toggle · Sound settings / Volume mixer · Exit.
.\AudioSwitchPS.ps1 -List # devices + profiles, asterisk = default
.\AudioSwitchPS.ps1 -Apply "Headset" # matches by name, partial match too
.\AudioSwitchPS.ps1 -SetOutput "*Realtek*"
.\AudioSwitchPS.ps1 -SetInput "*Jabra*"CLI mode exits immediately and never creates a tray icon — good for calling from another script, a desktop shortcut, or a PowerShell profile function.
%APPDATA%\AudioSwitchPS\audioswitchps.log, rotated at 1 MB. Levels: INFO, WARN, ERROR, PERF (profile apply / menu build time in ms).
- Only devices in the active state (
DEVICE_STATE_ACTIVE) are listed — disconnected or disabled devices won't show up. - If an AV product flags the compilation step during install: that's a one-time
csc.exerun, it never happens at runtime. If needed, build the DLL once on a reference machine and distribute the finished file. - The same
CN=NetSetPS Self-Signedcertificate can be reused to sign the code —Set-AuthenticodeSignatureon the*.ps1files and the DLL. - Both PS 5.1 and PS 7 work; the shortcuts deliberately target 5.1 (
System32\WindowsPowerShell\v1.0\powershell.exe) since it's always present.