Windows 10 can keep separate audio profiles for different audio devices. For each audio device that you connect, you can set a different volume level and when the device is connected, the volume will adjust automatically. Of course, no one keeps an audio device muted all the time. They will increase or decrease the volume but no one habitually mutes an audio device. If you use a pair of headphones with your desktop, and often have to disconnect them, you can use a little PowerShell script that will automatically mute sound when you unplug your headphones.

This is something that mobile phones do i.e., when you unplug your headphones, the music stops automatically. The logic behind this is that you’re either done listening to music or you’ve accidentally removed your headphones and you need a quick way to turn it off. The script was basically written on that same principle by Prateek Singh of GEEKEEFY.

Automatically Mute Sound

Open Notepad and paste the following;


#Adding definitions for accessing the Audio API
Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
// f(), g(), ... are unused COM method slots. Define these if you care
int f(); int g(); int h(); int i();
int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
int j();
int GetMasterVolumeLevelScalar(out float pfLevel);
int k(); int l(); int m(); int n();
int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
int GetMute(out bool pbMute);
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
int f(); // Unused
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
public class Audio {
static IAudioEndpointVolume Vol() {
var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
IMMDevice dev = null;
Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
IAudioEndpointVolume epv = null;
var epvid = typeof(IAudioEndpointVolume).GUID;
Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
return epv;
public static float Volume {
get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
public static bool Mute {
get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
'@ -Verbose

#Clean all events in the current session since its in a infinite loop, to make a fresh start when loop begins
Get-Event | Remove-Event -ErrorAction SilentlyContinue

#Registering the Event and Waiting for event to be triggered
Register-WmiEvent -Class Win32_DeviceChangeEvent
Wait-Event -OutVariable Event |Out-Null

$EventType = $Event.sourceargs.newevent | `
Sort-Object TIME_CREATED -Descending | `
Select-Object EventType -ExpandProperty EventType -First 1

#Conditional logic to handle, When to Mute/unMute the machine using Audio API
If($EventType -eq 3) 
[Audio]::Mute = $true
Write-Verbose "Muted [$((Get-Date).tostring())]"
elseif($EventType -eq 2 -and [Audio]::Mute -eq $true)
[Audio]::Mute = $false
Write-Verbose "UnMuted [$((Get-Date).tostring())]"

Save it with the PS1 file extension. Make sure you select ‘All Files’ from the file type dropdown. Give the file a name that will tell you at a glance what it does. Save it some place you’re unlikely to delete it by accident but also where you can find it easily if you need to.

Running The Script

PowerShell can’t just autorun a script. There is a built-in security measure the prevents it from doing so but there’s a way around it. We have a detailed article on how you can do just that. Follow the instructions to auto-run the PowerShell script you just created, and use a scheduled task to start the script every time you boot your PC.

if (navigator.appVersion.indexOf(“Mac”)!=-1) document.write(”);


Alternatively, you can manually run the script when you boot your system. I’ve been using it for less than 30 minutes and I don’t know how I was living without it before.