67

How can I change the Windows System Sound Volume using a C# Application?

2
  • Why did you remove the link for the duplicate? The Core Audio API's (Which control the mixer) don't just adjust single programs volumes, it is how you adjust the system volume too. Go actually read the answers in the duplicate and follow their links to the various MSDN articles. Commented Jul 13, 2014 at 16:02
  • But the answers in the duplicate do not provide the simplest solutions. Instead it suggests to use unneccessary libraries. Since my specific problem can easily be solved with built-in methods this is not a duplicate of the question linked as duplicate(Though it's pretty similar).
    – LostPhysx
    Commented Jul 25, 2015 at 10:14

7 Answers 7

91

I'm a bit late to the party but if you are looking now there's a nuget package available (AudioSwitcher.AudioApi.CoreAudio) that simplifies audio interactions. Install it then it’s as simple as:

CoreAudioDevice defaultPlaybackDevice = new CoreAudioController().DefaultPlaybackDevice;
Debug.WriteLine("Current Volume:" + defaultPlaybackDevice.Volume);
defaultPlaybackDevice.Volume = 80;
11
  • 3
    The exact package is mentioned above (AudioSwitcher.AudioApi.CoreAudio). So, in the Package Manager Console its "Install-Package AudioSwitcher.AudioApi.CoreAudio". More details at nuget.org/packages/AudioSwitcher.AudioApi.CoreAudio
    – Vman
    Commented Jan 24, 2017 at 16:36
  • 1
    For some reason, if I get a continuous loop of A first chance exception of type 'System.NullReferenceException' occurred in AudioSwitcher.AudioApi.CoreAudio.dll when I use this method. It's not stopping it from working but is there a way to eliminate this exception?
    – komodosp
    Commented Apr 3, 2017 at 10:49
  • 2
    can not use with .NET Core. Commented Mar 11, 2018 at 15:37
  • 1
    this should be the accepted solution, not those "scripting the gui", autoit-like thing...
    – beppe9000
    Commented May 21, 2018 at 21:22
  • 2
    AudioSwitcher.AudioApi.CoreAudio.dll is an abandoned buggy mess
    – Wobbles
    Commented Sep 19, 2019 at 13:43
57

Here is the code:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Test
{
    public class Test
    {
        private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
        private const int APPCOMMAND_VOLUME_UP = 0xA0000;
        private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
        private const int WM_APPCOMMAND = 0x319;

        [DllImport("user32.dll")]
        public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg,
            IntPtr wParam, IntPtr lParam);

        private void Mute()
        {
            SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
                (IntPtr)APPCOMMAND_VOLUME_MUTE);
        }

        private void VolDown()
        {
            SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
                (IntPtr)APPCOMMAND_VOLUME_DOWN);
        }

        private void VolUp()
        {
            SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle,
                (IntPtr)APPCOMMAND_VOLUME_UP);
        }
    }
}

Found on dotnetcurry

When using WPF you need to use new WindowInteropHelper(this).Handle instead of this.Handle (thanks Alex Beals)

5
  • I am trying to use this code in WPF app using C# , I am facing referencing problem at SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_VOLUME_MUTE); --- This.handle is not available in WPF . can u check ?
    – Apoorv
    Commented Jan 18, 2016 at 11:59
  • Maybe you could try to use the answer below. It shouldn't interfere with the limitations of WPF. (Or work with WinForms. It may be older but still a lot better (imho))
    – LostPhysx
    Commented Jan 21, 2016 at 15:24
  • 4
    Instead of this.Handle, use new WindowInteropHelper(this).Handle.
    – Alex Beals
    Commented Jan 22, 2016 at 7:04
  • Why is it not working for me in my WinForms app? Do I missed anything?
    – Leon Havin
    Commented Dec 17, 2016 at 0:30
  • 1
    Our WinForms app runs on a PC with Windows Explorer not running. This doesn't work without Windows Explorer running. I don't yet know a workaround.
    – Gutblender
    Commented Nov 20, 2019 at 19:47
17

If the tutorials provided in the other answers are too involved you could try an implementation like this using the keybd_event function

[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

Usage:

keybd_event((byte)Keys.VolumeUp, 0, 0, 0); // increase volume
keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume
4
  • 12
    But how to set the volume to 50%?
    – 62316e
    Commented Aug 1, 2013 at 7:41
  • 1
    It doesn't get much simpler than this, Might note that System.Windows.Forms is needed for the "keys" enum, but not required for the command. voldown = 174, volup = 175, volmute = 173 Commented Jan 5, 2016 at 0:19
  • @CasterTroy. This works great for simpler use cases without Windows Forms. And this approach provides zero dependency for any nuget packages. Spent hours for studying and trying other approaches and came back to this one. Kudos! And great thanks for this super smart solution!
    – Tagliner
    Commented Aug 22, 2019 at 13:40
  • And it appears it is compatible back to Windows 2000. I had to google for this version. It was post Win 98 version and one version before Win XP. Unlike alternative audio control implementations this is nice compatibility feature for home users who are still using Win XP.
    – Tagliner
    Commented Aug 22, 2019 at 15:41
15

In case you wish to set it to an exact value using the Core Audio APIs:

using CoreAudioApi;

public class SystemVolumeConfigurator
{
        private readonly MMDeviceEnumerator _deviceEnumerator = new MMDeviceEnumerator();
        private readonly MMDevice _playbackDevice;

        public SystemVolumeConfigurator()
        {
            _playbackDevice = _deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
        }

        public int GetVolume()
        {
            return (int)(_playbackDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100);
        }

        public void SetVolume(int volumeLevel)
        {
            if (volumeLevel < 0 || volumeLevel > 100)
                throw new ArgumentException("Volume must be between 0 and 100!");

            _playbackDevice.AudioEndpointVolume.MasterVolumeLevelScalar = volumeLevel / 100.0f;
        }
}
7
2

C# code:

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume
{
    int _0(); int _1(); int _2(); int _3();
    int SetMasterVolumeLevelScalar(float fLevel, Guid pguidEventContext);
    int _5();
    int GetMasterVolumeLevelScalar(out float pfLevel);
    int _7(); int _8(); int _9(); int _10(); int _11(); int _12();
}

[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 _0();
    int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}

[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }

public class Audio
{
    private static readonly IAudioEndpointVolume _MMVolume;

    static Audio()
    {
        var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
        enumerator.GetDefaultAudioEndpoint(0, 1, out IMMDevice dev);
        var aevGuid = typeof(IAudioEndpointVolume).GUID;
        dev.Activate(ref aevGuid, 1, 0, out _MMVolume);
    }

    public static int Volume
    {
        get
        {
            _MMVolume.GetMasterVolumeLevelScalar(out float level);
            return (int)(level * 100);
        }
        set
        {
            _MMVolume.SetMasterVolumeLevelScalar((float)value / 100, default);
        }
    }
}

Usage:

Audio.Volume = 50;

More info on MSDN.

1

You can add this library https://gist.github.com/sverrirs/d099b34b7f72bb4fb386 to your project and change the volume like this;

VideoPlayerController.AudioManager.SetMasterVolume(100);

The library also includes options for changing application volume, mute, getting current volume level etc. The namespace is called "Video Player Controller" but I used it in a Windows Forms App to change the system volume and it worked fine, so the "video" part is arbitrary.

1
  • I found this answer the most helpful because it sets the current device volume, not just the default device volume. This means you can switch playback devices and still have volume control without taking any additional steps. Certainly, setting the current device volume is also possible using CoreAudio directly, but you must take extra steps to find the current playback device. At the end of the day, this solution uses CoreAudio like the others, but wraps it in a pretty convenient package, all enclosed in a single file. Clear and concise.
    – Brian K
    Commented Jan 25, 2022 at 23:17
0

My code is a bit different but still using CoreAudio

downloaded the pkg : nuget install AudioSwitcher.AudioApi.CoreAudio -Version 3.0.0.1

using AudioSwitcher.AudioApi.CoreAudio;
public partial class MainWindow : Window
{
public MainWindow()
{

InitializeComponent();

CoreAudioDevice defaultPlaybackDevice = new CoreAudioController().DefaultPlaybackDevice;

double vol = defaultPlaybackDevice.Volume;

defaultPlaybackDevice.Volume = defaultPlaybackDevice.Volume - 5.0;

defaultPlaybackDevice.Volume = defaultPlaybackDevice.Volume + 5.0;
}
}
1
  • 2
    Why is this library so slow? Commented Aug 27, 2020 at 22:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.