You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中设置Windows10/11默认麦克风设备(非PowerShell方案)

在C#中设置Windows默认麦克风设备(无需PowerShell)

winmm.dll中不存在waveInSetDefault API,要设置默认音频输入设备,需借助Windows Core Audio API(MMDeviceAPI),通过COM互操作实现,无需依赖PowerShell。以下是完整的C#实现方案:

核心COM接口与枚举定义

这些定义对应Windows Core Audio的原生接口,用于设备枚举和默认设置操作:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;

// Core Audio API 相关COM类与接口
[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
internal class MMDeviceEnumerator
{
}

[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDeviceEnumerator
{
    void NotImpl1();
    int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
    int EnumAudioEndpoints(EDataFlow dataFlow, EDeviceState stateMask, out IMMDeviceCollection ppDevices);
}

[Guid("0BD7A1BE-7A1A-44DB-8397-CC5392387B5E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDeviceCollection
{
    int GetCount(out uint pcDevices);
    int Item(uint nDevice, out IMMDevice ppDevice);
}

[Guid("D666063F-1587-4E43-81F1-B948E807363F")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDevice
{
    int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, out IntPtr ppInterface);
    int OpenPropertyStore(int stgmAccess, out IPropertyStore ppProperties);
    int GetId(out IntPtr ppstrId);
    int GetState(out uint pdwState);
}

[Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IPropertyStore
{
    int GetCount(out uint cProps);
    int GetAt(uint iProp, out PropertyKey pkey);
    int GetValue(ref PropertyKey key, out PropVariant pv);
    int SetValue(ref PropertyKey key, ref PropVariant pv);
    int Commit();
}

// 设置默认设备的核心接口
[Guid("1BE09788-6894-4089-8586-9A2A6C265AC5")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IPolicyConfig
{
    int NotImpl1();
    int NotImpl2();
    int SetDefaultEndpoint(string pszDeviceId, ERole role);
}

[ComImport]
[Guid("870AF99C-171D-4F9E-AF0D-E63DF40C2BC9")]
internal class PolicyConfigClient
{
}

// 枚举定义
internal enum EDataFlow
{
    eRender,
    eCapture,
    eAll,
}

internal enum ERole
{
    eConsole,
    eMultimedia,
    eCommunications,
}

internal enum EDeviceState
{
    Active = 0x00000001,
    Disabled = 0x00000002,
    NotPresent = 0x00000004,
    Unplugged = 0x00000008,
    All = 0x0000000F,
}

// 辅助结构体
[StructLayout(LayoutKind.Sequential)]
internal struct PropertyKey
{
    public Guid fmtid;
    public uint pid;
}

[StructLayout(LayoutKind.Explicit)]
internal struct PropVariant
{
    [FieldOffset(0)] private ushort vt;
    [FieldOffset(8)] private IntPtr pwszVal;

    public string StringValue => Marshal.PtrToStringUni(pwszVal);
}

设备管理工具类

封装设备枚举和默认设置的方法:

public static class AudioDeviceManager
{
    // 获取所有活跃的麦克风设备
    public static List<(string Id, string Name)> GetAllActiveMicrophones()
    {
        var devices = new List<(string, string)>();
        var enumerator = (IMMDeviceEnumerator)new MMDeviceEnumerator();
        
        try
        {
            enumerator.EnumAudioEndpoints(EDataFlow.eCapture, EDeviceState.Active, out var deviceCollection);
            deviceCollection.GetCount(out uint count);

            for (uint i = 0; i < count; i++)
            {
                deviceCollection.Item(i, out var device);
                device.GetId(out IntPtr idPtr);
                string deviceId = Marshal.PtrToStringUni(idPtr);
                Marshal.FreeCoTaskMem(idPtr);

                device.OpenPropertyStore(0, out var props);
                var nameKey = new PropertyKey
                {
                    fmtid = new Guid("A45C254E-DF1C-4EFD-8020-67D146A850E0"), // PKEY_Device_FriendlyName
                    pid = 14
                };
                props.GetValue(ref nameKey, out var nameVar);
                string deviceName = nameVar.StringValue;

                devices.Add((deviceId, deviceName));
                
                Marshal.ReleaseComObject(props);
                Marshal.ReleaseComObject(device);
            }
            
            Marshal.ReleaseComObject(deviceCollection);
        }
        finally
        {
            Marshal.ReleaseComObject(enumerator);
        }

        return devices;
    }

    // 根据设备名称模糊匹配设置默认麦克风
    public static bool SetDefaultMicrophone(string deviceNameMatch)
    {
        var microphones = GetAllActiveMicrophones();
        var targetMic = microphones.FirstOrDefault(m => 
            m.Name.Contains(deviceNameMatch, StringComparison.OrdinalIgnoreCase));
        
        if (targetMic.Equals(default))
            return false;

        var policyConfig = (IPolicyConfig)new PolicyConfigClient();
        try
        {
            // 同时设置多媒体默认和通信默认设备
            policyConfig.SetDefaultEndpoint(targetMic.Id, ERole.eMultimedia);
            policyConfig.SetDefaultEndpoint(targetMic.Id, ERole.eCommunications);
            return true;
        }
        finally
        {
            Marshal.ReleaseComObject(policyConfig);
        }
    }
}

调用示例

// 设置名称包含"Mic"的设备为默认麦克风
bool success = AudioDeviceManager.SetDefaultMicrophone("Mic");
if (success)
{
    Console.WriteLine("默认麦克风设置成功");
}
else
{
    Console.WriteLine("未找到匹配的麦克风设备");
}

关键说明

  • ERole.eMultimedia对应系统"默认设备",ERole.eCommunications对应"默认通信设备",通常需要同时设置两者
  • 设备名称匹配采用模糊匹配,可根据需求调整为精确匹配
  • 所有COM对象使用后需调用Marshal.ReleaseComObject释放,避免内存泄漏
  • 项目需设置为x64或x86平台,AnyCPU模式可能出现COM互操作异常

内容的提问来源于stack exchange,提问作者Kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:45:01