能否通过PowerShell获取/设置Win10/11系统声音音量或设备主音量?
用PowerShell获取/设置Windows设备主音量与系统声音音量
完全可以在Win10/Win11上用PowerShell实现这两个需求,以下是具体实现方案:
一、设备主音量(Master Volume)
获取当前主音量百分比
通过调用Windows Core Audio API实现,PowerShell代码如下:
Add-Type -TypeDefinition @' using System; using System.Runtime.InteropServices; public class AudioManager { [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioEndpointVolume { int NotImpl1(); int NotImpl2(); int GetMasterVolumeLevelScalar(out float level); int SetMasterVolumeLevelScalar(float level, Guid eventContext); int NotImpl3(); int NotImpl4(); int GetMute(out bool mute); int SetMute(bool mute, Guid eventContext); } [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDevice { int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out IntPtr ppInterface); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDeviceEnumerator { int NotImpl1(); int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice); } [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] private class MMDeviceEnumeratorComObject { } public static float GetMasterVolume() { IMMDeviceEnumerator enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; IMMDevice device = null; enumerator.GetDefaultAudioEndpoint(0, 0, out device); Guid iid = typeof(IAudioEndpointVolume).GUID; IntPtr ptr = IntPtr.Zero; device.Activate(ref iid, 0x17, IntPtr.Zero, out ptr); IAudioEndpointVolume volume = Marshal.GetObjectForIUnknown(ptr) as IAudioEndpointVolume; float level = 0; volume.GetMasterVolumeLevelScalar(out level); Marshal.Release(ptr); return level * 100; } } '@ [AudioManager]::GetMasterVolume()
设置主音量(示例:设置为50%)
基于同样的API封装,代码如下:
Add-Type -TypeDefinition @' using System; using System.Runtime.InteropServices; public class AudioManager { [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioEndpointVolume { int NotImpl1(); int NotImpl2(); int GetMasterVolumeLevelScalar(out float level); int SetMasterVolumeLevelScalar(float level, Guid eventContext); int NotImpl3(); int NotImpl4(); int GetMute(out bool mute); int SetMute(bool mute, Guid eventContext); } [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDevice { int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out IntPtr ppInterface); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDeviceEnumerator { int NotImpl1(); int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice); } [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] private class MMDeviceEnumeratorComObject { } public static void SetMasterVolume(float level) { if (level < 0 || level > 100) throw new ArgumentOutOfRangeException(nameof(level)); IMMDeviceEnumerator enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; IMMDevice device = null; enumerator.GetDefaultAudioEndpoint(0, 0, out device); Guid iid = typeof(IAudioEndpointVolume).GUID; IntPtr ptr = IntPtr.Zero; device.Activate(ref iid, 0x17, IntPtr.Zero, out ptr); IAudioEndpointVolume volume = Marshal.GetObjectForIUnknown(ptr) as IAudioEndpointVolume; volume.SetMasterVolumeLevelScalar(level / 100, Guid.Empty); Marshal.Release(ptr); } } '@ # 设置主音量为50% [AudioManager]::SetMasterVolume(50)
二、系统声音音量(System Sounds)
系统声音属于独立的音频会话,需定位到该会话后调整:
获取系统声音当前音量百分比
Add-Type -TypeDefinition @' using System; using System.Runtime.InteropServices; [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionManager2 { int NotImpl1(); int NotImpl2(); int GetSessionEnumerator(out IntPtr sessionEnumerator); } [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionEnumerator { int GetCount(out int count); int GetSession(int index, out IntPtr sessionControl); } [Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionControl2 { int NotImpl1(); int NotImpl2(); int GetDisplayName(out string displayName); int SetDisplayName(string displayName, Guid eventContext); int GetIconPath(out string iconPath); int SetIconPath(string iconPath, Guid eventContext); int GetGroupingParam(out Guid groupingParam); int SetGroupingParam(Guid groupingParam, Guid eventContext); int NotImpl3(); int GetSessionIdentifier(out string sessionId); int GetSessionInstanceIdentifier(out string instanceId); int GetProcessId(out uint processId); int IsSystemSoundsSession(); int SetDuckingPreference(bool optOut); } [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface ISimpleAudioVolume { int SetMasterVolume(float volume, Guid eventContext); int GetMasterVolume(out float volume); int SetMute(bool mute, Guid eventContext); int GetMute(out bool mute); } [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] private class MMDeviceEnumeratorComObject { } [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDevice { int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out IntPtr ppInterface); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDeviceEnumerator { int NotImpl1(); int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice); } public class SystemSoundVolume { public static float GetSystemSoundVolume() { IMMDeviceEnumerator enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; IMMDevice device = null; enumerator.GetDefaultAudioEndpoint(0, 0, out device); Guid sessionManagerGuid = typeof(IAudioSessionManager2).GUID; IntPtr sessionManagerPtr = IntPtr.Zero; device.Activate(ref sessionManagerGuid, 0x17, IntPtr.Zero, out sessionManagerPtr); IAudioSessionManager2 sessionManager = Marshal.GetObjectForIUnknown(sessionManagerPtr) as IAudioSessionManager2; IntPtr sessionEnumeratorPtr = IntPtr.Zero; sessionManager.GetSessionEnumerator(out sessionEnumeratorPtr); IAudioSessionEnumerator sessionEnumerator = Marshal.GetObjectForIUnknown(sessionEnumeratorPtr) as IAudioSessionEnumerator; sessionEnumerator.GetCount(out int sessionCount); float systemVolume = 0; for (int i = 0; i < sessionCount; i++) { IntPtr sessionControlPtr = IntPtr.Zero; sessionEnumerator.GetSession(i, out sessionControlPtr); IAudioSessionControl2 sessionControl2 = Marshal.GetObjectForIUnknown(sessionControlPtr) as IAudioSessionControl2; int isSystem = sessionControl2.IsSystemSoundsSession(); if (isSystem == 0) { IntPtr simpleVolumePtr = IntPtr.Zero; Guid simpleVolumeGuid = typeof(ISimpleAudioVolume).GUID; Marshal.QueryInterface(sessionControlPtr, ref simpleVolumeGuid, out simpleVolumePtr); ISimpleAudioVolume simpleVolume = Marshal.GetObjectForIUnknown(simpleVolumePtr) as ISimpleAudioVolume; simpleVolume.GetMasterVolume(out float volume); systemVolume = volume * 100; Marshal.Release(simpleVolumePtr); } Marshal.Release(sessionControlPtr); } Marshal.Release(sessionEnumeratorPtr); Marshal.Release(sessionManagerPtr); return systemVolume; } } '@ [SystemSoundVolume]::GetSystemSoundVolume()
设置系统声音音量(示例:设置为30%)
Add-Type -TypeDefinition @' using System; using System.Runtime.InteropServices; [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionManager2 { int NotImpl1(); int NotImpl2(); int GetSessionEnumerator(out IntPtr sessionEnumerator); } [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionEnumerator { int GetCount(out int count); int GetSession(int index, out IntPtr sessionControl); } [Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionControl2 { int NotImpl1(); int NotImpl2(); int GetDisplayName(out string displayName); int SetDisplayName(string displayName, Guid eventContext); int GetIconPath(out string iconPath); int SetIconPath(string iconPath, Guid eventContext); int GetGroupingParam(out Guid groupingParam); int SetGroupingParam(Guid groupingParam, Guid eventContext); int NotImpl3(); int GetSessionIdentifier(out string sessionId); int GetSessionInstanceIdentifier(out string instanceId); int GetProcessId(out uint processId); int IsSystemSoundsSession(); int SetDuckingPreference(bool optOut); } [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface ISimpleAudioVolume { int SetMasterVolume(float volume, Guid eventContext); int GetMasterVolume(out float volume); int SetMute(bool mute, Guid eventContext); int GetMute(out bool mute); } [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] private class MMDeviceEnumeratorComObject { } [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDevice { int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out IntPtr ppInterface); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IMMDeviceEnumerator { int NotImpl1(); int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice); } public class SystemSoundVolume { public static void SetSystemSoundVolume(float level) { if (level < 0 || level > 100) throw new ArgumentOutOfRangeException(nameof(level)); IMMDeviceEnumerator enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator; IMMDevice device = null; enumerator.GetDefaultAudioEndpoint(0, 0, out device); Guid sessionManagerGuid = typeof(IAudioSessionManager2).GUID; IntPtr sessionManagerPtr = IntPtr.Zero; device.Activate(ref sessionManagerGuid, 0x17, IntPtr.Zero, out sessionManagerPtr); IAudioSessionManager2 sessionManager = Marshal.GetObjectForIUnknown(sessionManagerPtr) as IAudioSessionManager2; IntPtr sessionEnumeratorPtr = IntPtr.Zero; sessionManager.GetSessionEnumerator(out sessionEnumeratorPtr); IAudioSessionEnumerator sessionEnumerator = Marshal.GetObjectForIUnknown(sessionEnumeratorPtr) as IAudioSessionEnumerator; sessionEnumerator.GetCount(out int sessionCount); for (int i = 0; i < sessionCount; i++) { IntPtr sessionControlPtr = IntPtr.Zero; sessionEnumerator.GetSession(i, out sessionControlPtr); IAudioSessionControl2 sessionControl2 = Marshal.GetObjectForIUnknown(sessionControlPtr) as IAudioSessionControl2; int isSystem = sessionControl2.IsSystemSoundsSession(); if (isSystem == 0) { IntPtr simpleVolumePtr = IntPtr.Zero; Guid simpleVolumeGuid = typeof(ISimpleAudioVolume).GUID; Marshal.QueryInterface(sessionControlPtr, ref simpleVolumeGuid, out simpleVolumePtr); ISimpleAudioVolume simpleVolume = Marshal.GetObjectForIUnknown(simpleVolumePtr) as ISimpleAudioVolume; simpleVolume.SetMasterVolume(level / 100, Guid.Empty); Marshal.Release(simpleVolumePtr); } Marshal.Release(sessionControlPtr); } Marshal.Release(sessionEnumeratorPtr); Marshal.Release(sessionManagerPtr); } } '@ # 设置系统声音音量为30% [SystemSoundVolume]::SetSystemSoundVolume(30)
说明
- 以上代码基于Windows Core Audio API实现,无需额外安装模块,原生PowerShell即可运行
- 代码中
0x17是CLSCTX_ALL的常量值,用于COM对象激活 - 系统声音会话通过
IsSystemSoundsSession()方法识别,返回0表示是目标会话
内容的提问来源于stack exchange,提问作者Bbb
相关产品推荐
相关产品推荐

