如何通过编程设置系统音量?

65

我如何使用C#应用程序更改Windows系统声音的音量?


你为什么删除了重复的链接?核心音频API(控制混音器)不仅可以调整单个程序的音量,还可以调整系统音量。去阅读重复问题中的答案,并跟随它们的链接到各种MSDN文章。 - Scott Chamberlain
但是重复问题中的答案并没有提供最简单的解决方案。相反,它建议使用不必要的库。由于我的特定问题可以轻松地使用内置方法解决,因此这不是与链接为重复的问题相同(尽管非常相似)。 - LostPhysx
7个回答

90

我有些晚了,但如果你现在正在寻找,有一个NuGet包可用 (AudioSwitcher.AudioApi.CoreAudio),简化音频交互。安装后,只需要:

CoreAudioDevice defaultPlaybackDevice = new CoreAudioController().DefaultPlaybackDevice;
Debug.WriteLine("Current Volume:" + defaultPlaybackDevice.Volume);
defaultPlaybackDevice.Volume = 80;

3
以上已经提到了确切的软件包名称(AudioSwitcher.AudioApi.CoreAudio)。在包管理器控制台中,需要输入"Install-Package AudioSwitcher.AudioApi.CoreAudio"来安装该软件包。更多详情请参考https://www.nuget.org/packages/AudioSwitcher.AudioApi.CoreAudio/。 - Vman
1
由于某种原因,当我使用这个方法时,会出现“System.NullReferenceException”类型的连续循环异常在AudioSwitcher.AudioApi.CoreAudio.dll中发生。虽然它没有阻止它的工作,但有没有办法消除这个异常? - komodosp
1
无法与.NET Core一起使用。 - Sabir Hossain
1
这应该是被接受的解决方案,而不是那些“脚本化GUI”,类似AutoIt的东西... - beppe9000
2
AudioSwitcher.AudioApi.CoreAudio.dll是一个被遗弃的有缺陷的混乱文件。 - Wobbles
显示剩余5条评论

57

这里是代码:

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);
        }
    }
}

文章来源于 dotnetcurry

在使用WPF时,需要使用new WindowInteropHelper(this).Handle代替this.Handle (感谢Alex Beals提供的信息)


我正在尝试在使用C#的WPF应用程序中使用此代码,我在SendMessageW(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_VOLUME_MUTE)遇到引用问题。---This.handle在WPF中不可用。你能检查一下吗? - Apoorv
也许你可以尝试使用下面的答案。它不应该干扰WPF的限制。(或者使用WinForms。它可能更老,但在我看来仍然好得多) - LostPhysx
4
请使用new WindowInteropHelper(this).Handle代替this.Handle - Alex Beals
我的WinForms应用程序为什么不能工作?我有什么遗漏吗? - Leon Havin
1
我们的WinForms应用程序在没有运行Windows Explorer的PC上运行。如果没有Windows Explorer运行,这是不起作用的。我还不知道有什么解决方法。 - Gutblender

17
如果其他答案中提供的教程太复杂,您可以尝试使用类似这样的实现,使用keybd_event函数
[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

使用方法:

keybd_event((byte)Keys.VolumeUp, 0, 0, 0); // increase volume
keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume

12
如何将音量设置为50%? - 62316e
1
它再简单不过了。可能需要 System.Windows.Forms 来使用“keys”枚举,但是对于命令并非必须。voldown = 174, volup = 175, volmute = 173。 - DiamondDrake
@CasterTroy。这对于没有Windows Forms的简单用例非常有效。而且这种方法不需要任何nuget包的依赖。花了几个小时研究和尝试其他方法,最终回到了这个方法。致敬!非常感谢这个超级聪明的解决方案! - Tagliner
它似乎兼容Windows 2000及以后的版本。我不得不通过谷歌搜索这个版本。这是Win 98版本之后的一个版本,也是Win XP之前的一个版本。与其他音频控制实现不同,这是一个很好的兼容性功能,适用于仍在使用Win XP的家庭用户。 - Tagliner

15

如果您想要使用核心音频API将其设置为精确值:

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;
        }
}

这是一篇关于.NET Core Audio的文章,提供了API下载链接。 - Dman
2
对于任何试图找到此API的人,它已经迁移到GitHub https://github.com/filoe/cscore,并且在本评论中,引用为`using CSCore.CoreAudioAPI;`。 - Simple Sandman
@SimpleSandman 他们又更新了API...我刚刚查看了相关的测试,以获取最新的示例:https://github.com/filoe/cscore/blob/master/CSCore.Test/CoreAudioAPI/EndpointTests.cs - jklemmack
EDataFlowERole 究竟是什么? - Koenigsberg
我来这里之前已经做过了,但是对于using等仍然不太清楚。 - Koenigsberg
显示剩余2条评论

1

C#代码:

[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);
        }
    }
}

使用方法:

Audio.Volume = 50;

更多信息请参见MSDN


1
你可以将这个库https://gist.github.com/sverrirs/d099b34b7f72bb4fb386添加到你的项目中,然后像这样更改音量;
VideoPlayerController.AudioManager.SetMasterVolume(100);

该库还包括更改应用程序音量、静音、获取当前音量级别等选项。命名空间称为“Video Player Controller”,但我在Windows Forms应用程序中使用它来更改系统音量,效果很好,因此“video”部分是任意的。

我认为这个答案最有帮助,因为它设置了当前设备的音量,而不仅仅是默认设备的音量。这意味着您可以切换播放设备并仍然具有音量控制,而无需采取任何其他步骤。当然,直接使用CoreAudio也可以设置当前设备的音量,但您必须采取额外的步骤来查找当前的播放设备。归根结底,这个解决方案像其他解决方案一样使用CoreAudio,但将其包装在一个相当方便的包中,所有内容都封装在一个单独的文件中。清晰简洁。 - Brian K

0

我的代码有点不同,但仍然使用CoreAudio

下载了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;
}
}

2
为什么这个库如此缓慢? - uncommon_name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接