C#修改自身进程音量遇访问权限问题,求可行替代方案
解决C#修改自身进程音量的问题
你遇到的ISimpleAudioVolume、IAudioSessionEnumerator等接口无法访问的问题,核心原因是这些Windows音频会话的COM接口没有在代码中显式定义为public,或者你没有包含完整的接口定义代码。下面提供两种可行的解决方案:
方案一:原生Windows API实现(无第三方依赖)
首先需要把所有用到的COM接口、枚举都显式定义为public,保证代码能正常访问:
using System; using System.Runtime.InteropServices; using System.Diagnostics; // 音频设备流向枚举 public enum EDataFlow { eRender, eCapture, eAll, EDataFlow_enum_count } // 音频角色枚举 public enum ERole { eConsole, eMultimedia, eCommunications, ERole_enum_count } // 设备枚举器接口 [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMMDeviceEnumerator { void NotImpl1(); void GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice); } // 音频设备接口 [Guid("D666063F-1587-4E43-81F1-B948E807363F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IMMDevice { void Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out object ppInterface); } // 音频会话管理器接口 [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionManager2 { void NotImpl1(); void NotImpl2(); void GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum); } // 音频会话枚举器接口 [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionEnumerator { void GetCount(out int SessionCount); void GetSession(int SessionCount, out IAudioSessionControl Session); } // 音频会话控制接口 [Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionControl { void NotImpl1(); void GetDisplayName(out string pRetVal); } // 扩展音频会话控制接口(用于获取进程ID) [Guid("bfb7ff88-7239-4fc9-8fa2-07c950be9c6d")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IAudioSessionControl2 : IAudioSessionControl { new void NotImpl1(); new void GetDisplayName(out string pRetVal); void GetProcessId(out uint pRetVal); } // 音量控制接口 [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISimpleAudioVolume { void SetMasterVolume(float fLevel, ref Guid EventContext); void GetMasterVolume(out float pfLevel); void SetMute(bool bMute, ref Guid EventContext); void GetMute(out bool pbMute); } // 设备枚举器COM类 [ComImport] [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] public class MMDeviceEnumerator { } // 修改自身进程音量的核心方法 public static void SetSelfApplicationVolume(float level) { int currentPid = Process.GetCurrentProcess().Id; ISimpleAudioVolume volume = GetVolumeObject(currentPid); if (volume == null) return; Guid guid = Guid.Empty; volume.SetMasterVolume(level / 100, ref guid); } private static ISimpleAudioVolume GetVolumeObject(int processId) { IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator(); IMMDevice speakers; deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers); Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID; object o; speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o); IAudioSessionManager2 mgr = (IAudioSessionManager2)o; IAudioSessionEnumerator sessionEnumerator; mgr.GetSessionEnumerator(out sessionEnumerator); int count; sessionEnumerator.GetCount(out count); ISimpleAudioVolume volumeControl = null; for (int i = 0; i < count; i++) { IAudioSessionControl ctl; sessionEnumerator.GetSession(i, out ctl); IAudioSessionControl2 ctl2 = ctl as IAudioSessionControl2; if (ctl2 != null) { uint pid; ctl2.GetProcessId(out pid); if (pid == processId) { volumeControl = ctl as ISimpleAudioVolume; break; } } Marshal.ReleaseComObject(ctl); } Marshal.ReleaseComObject(sessionEnumerator); Marshal.ReleaseComObject(mgr); Marshal.ReleaseComObject(speakers); Marshal.ReleaseComObject(deviceEnumerator); return volumeControl; }
调用示例:
// 设置自身进程音量为50% SetSelfApplicationVolume(50);
方案二:使用NAudio库(更简洁)
NAudio是封装了Windows音频API的开源库,能大幅简化代码:
- 先通过NuGet安装NAudio包;
- 使用以下代码修改自身进程音量:
using NAudio.CoreAudioApi; using System.Diagnostics; public static void SetSelfVolume(float level) { using (var sessionManager = new AudioSessionManager2()) { foreach (var session in sessionManager.Sessions) { if (session.ProcessID == Process.GetCurrentProcess().Id) { session.SimpleAudioVolume.Volume = level / 100; break; } } } }
调用示例:
// 设置自身进程音量为30% SetSelfVolume(30);
内容的提问来源于stack exchange,提问作者progExpic4
相关产品推荐
相关产品推荐

