C# 静音其他应用程序

C# mute other application

我正在构建一个自动启动屏幕录像机应用程序(如 OBS)的应用程序(以录制缩放会议)。

我不想在录制过程中播放任何其他应用程序的音频,但我找不到有效代码。

我使用示例 in this site with some code from here 只是为了检查 API

public enum MMRESULT : uint
{
    // Source: https://www.pinvoke.net/default.aspx/winmm/MMRESULT.html?diff=y
    MMSYSERR_NOERROR    = 0,
    MMSYSERR_ERROR      = 1,
    MMSYSERR_BADDEVICEID    = 2,
    MMSYSERR_NOTENABLED     = 3,
    MMSYSERR_ALLOCATED      = 4,
    MMSYSERR_INVALHANDLE    = 5,
    MMSYSERR_NODRIVER       = 6,
    MMSYSERR_NOMEM      = 7,
    MMSYSERR_NOTSUPPORTED   = 8,
    MMSYSERR_BADERRNUM      = 9,
    MMSYSERR_INVALFLAG      = 10,
    MMSYSERR_INVALPARAM     = 11,
    MMSYSERR_HANDLEBUSY     = 12,
    MMSYSERR_INVALIDALIAS   = 13,
    MMSYSERR_BADDB      = 14,
    MMSYSERR_KEYNOTFOUND    = 15,
    MMSYSERR_READERROR      = 16,
    MMSYSERR_WRITEERROR     = 17,
    MMSYSERR_DELETEERROR    = 18,
    MMSYSERR_VALNOTFOUND    = 19,
    MMSYSERR_NODRIVERCB     = 20,
    WAVERR_BADFORMAT    = 32,
    WAVERR_STILLPLAYING     = 33,
    WAVERR_UNPREPARED       = 34
}

[DllImport("winmm.dll")]
public static extern MMRESULT waveOutGetVolume(IntPtr hwo, out uint dwVolume);
[DllImport("winmm.dll")]
public static extern MMRESULT waveOutSetVolume(IntPtr hwo, uint dwVolume);
public static void Main(string[] args)
{
    foreach (Process process in Process.GetProcesses())
    {
        if (process.MainWindowHandle != IntPtr.Zero)
        {
            // Source: https://sites.google.com/site/lalitpundir/s-1
            try
            {
                uint CurrVol = 0;
                // At this point, CurrVol gets assigned the volume
                MMRESULT res = waveOutGetVolume(process.Handle, out CurrVol);
                // Calculate the volume
                ushort CalcVol = (ushort)(CurrVol & 0x0000ffff);
                // Get the volume on a scale of 1 to 10 (to fit the trackbar)
                Console.WriteLine($"The volume of {process.ProcessName} is {CalcVol / (ushort.MaxValue / 10)}");
                // Try muting chrome
                if (process.ProcessName.Equals("chrome"))
                {
                    Console.WriteLine("Muting chrome");
                    int NewVolume = 0;
                    uint NewVolumeAllChannels = (((uint)NewVolume & 0x0000ffff) | ((uint)NewVolume << 16));
                    res = waveOutSetVolume(process.Handle, NewVolumeAllChannels);
                    Console.WriteLine(res);
                    Thread.Sleep(5000);
                }
            }
            catch (Win32Exception e)
            {
                Console.WriteLine($"Error with {process.ProcessName}");
            }
        }
    }

}

上面的代码,对于waveOutGetVolumewaveOutSetVolume方法总是returnsMMSYSERR_BADDEVICEID

谢谢你Make that 4的帮助。

您提供的链接帮助我找到了 this answer,我对其进行了一些修改以满足我的需要。

首先,这个答案需要NuGet包CSCore

这是我使用的示例代码(我还在学习包):

public class MixerTest
{
    static void Main(string[] args)
    {
        foreach (AudioSessionManager2 sessionManager in GetDefaultAudioSessionManager2(DataFlow.Render))
        {
            using (sessionManager)
            {
                using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
                {
                    foreach (var session in sessionEnumerator)
                    {
                        using var simpleVolume = session.QueryInterface<SimpleAudioVolume>();
                        using var sessionControl = session.QueryInterface<AudioSessionControl2>();
                        Console.WriteLine((sessionControl.Process.ProcessName, sessionControl.SessionIdentifier));
                        if (Process.GetProcessById(sessionControl.ProcessID).ProcessName.Equals("chrome"))
                        {
                            simpleVolume.IsMuted = true;
                        }
                    }
                }
            }
        }

        Console.ReadKey();
    }
    private static IEnumerable<AudioSessionManager2> GetDefaultAudioSessionManager2(DataFlow dataFlow)
    {
        using var enumerator = new MMDeviceEnumerator();
        using var devices = enumerator.EnumAudioEndpoints(dataFlow, DeviceState.Active);
        foreach (var device in devices)
        {
            Console.WriteLine("Device: " + device.FriendlyName);
            var sessionManager = AudioSessionManager2.FromMMDevice(device);
            yield return sessionManager;
        }
    }
}