【问题标题】:How to identify the default audio device in Powershell?如何识别 Powershell 中的默认音频设备?
【发布时间】:2020-04-11 02:20:35
【问题描述】:

我正在寻找通过 Powershell 获取默认音频设备的解决方案。 在最好的情况下,它可以通过嵌入式 C# 代码直接使用 IMMDeviceEnumerator::GetDefaultAudioEndpoint(参见此处IMMDeviceEnumertor)。

但如果通过 RegKeys 更容易获得它,那么这也是可以的。 我已经看到几个 code-sn-ps 从 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render 或 \Capture 读取密钥,但我仍然难以识别 DEFAULT 设备。

看来,当我修改设备的顺序时,我可以简单地搜索活动设备(DeviceState=1),然后按值“Level:0”、“Level:1”和“Level:2”排序",但级别值在用户未手动修改订单的系统上不可用。在这种情况下,排序标准是什么?

这是通过 RegKeys 解决它的 code-sn-p,但如前所述 - 并非适用于所有情况:

$regAudio =  "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio"
$nameId = "{b3f8fa53-0004-438e-9003-51a46e139bfc},6"
$classId = "{a45c254e-df1c-4efd-8020-67d146a850e0},2"
$driverDetails = "{83da6326-97a6-4088-9453-a1923f573b29},3"

function get-DefaultDevice($type) {
    $activeDevices = foreach($key in  Get-ChildItem "$regAudio\$type\") {
        foreach($item in Get-ItemProperty $key.PsPath) { 
            if ($item.DeviceState -eq $activeState) {$item}
        }
    }
    $defaultDevice = $activeDevices | Sort-Object -Property "Level:0","Level:1","Level:2" | select -last 1
    $details = Get-ItemProperty "$($defaultDevice.PSPath)\Properties"
    $name = "$($details.$classId) ($($details.$nameId))"
    return @{
        name   = $name
        driver = $details.$driverDetails
    }
}

$OsRender = get-DefaultDevice "Render"
$OsCapture = get-DefaultDevice "Capture"

有没有办法“以一种智能的方式”获取这些信息(当然,没有任何外部 DLL)?

【问题讨论】:

    标签: powershell audio-device


    【解决方案1】:

    我终于弄明白了,我很高兴分享工作代码-sn-p:

    cls
    Add-Type -TypeDefinition @'
    using System.Runtime.InteropServices;
    [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IMMDevice {
        int a(); int o();
        int GetId([MarshalAs(UnmanagedType.LPWStr)] out string id);
    }
    [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IMMDeviceEnumerator {
        int f();
        int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
    }
    [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
    public class Audio {
        public static string GetDefault (int direction) {
        var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
        IMMDevice dev = null;
        Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(direction, 1, out dev));
        string id = null;
        Marshal.ThrowExceptionForHR(dev.GetId(out id));
        return id;
        }
    }
    '@
    
    function getFriendlyName($id) {
        $reg = "HKLM:\SYSTEM\CurrentControlSet\Enum\SWD\MMDEVAPI\$id"
        return (get-ItemProperty $reg).FriendlyName
    }
    
    $id0 = [audio]::GetDefault(0)
    $id1 = [audio]::GetDefault(1)
    write-host "Default Speaker: $(getFriendlyName $id0)" 
    write-host "Default Micro  : $(getFriendlyName $id1)"
    

    【讨论】:

    • 解决方案的浏览量超过 1000 次,但没有投票支持 - 我不明白。
    • 您好,先生,当我能够正常运行时,实际上这段代码非常好。有时它会给我一个错误,不知道为什么......无论如何,这是一部出色的作品! :-) 谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 2011-09-04
    • 2019-11-10
    相关资源
    最近更新 更多