如何识别Powershell中的默认音频设备?

Car*_*ten 5 powershell audio-device

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

但如果通过 RegKeys 更容易获得它,那么这也可以。我已经看到一些代码片段从 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render 或 \Capture 读取密钥,但我仍然很难识别默认设备。

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

这是通过 RegKeys 解决该问题的代码片段,但如上所述 - 不适用于所有情况:

$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"
Run Code Online (Sandbox Code Playgroud)

有什么方法可以“以智能方式”获取此信息(当然,无需任何外部 DLL)?

Car*_*ten 11

最后我想通了,我很高兴分享工作代码片段:

cls
Add-Type @'
[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 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;
}
'@ -name audio -Namespace system

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)"
Run Code Online (Sandbox Code Playgroud)

如果您需要每个设备 MMDEVICE-id 及其驱动程序(可选)的语言中立的国际名称,请使用此函数:

# https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/devpkey.h
# https://github.com/EddieRingle/portaudio/blob/master/src/hostapi/wasapi/mingw-include/mmdeviceapi.h
$regId         = "{b3f8fa53-0004-438e-9003-51a46e139bfc},2"
$regName       = "{b3f8fa53-0004-438e-9003-51a46e139bfc},6"
$regFormFactor = "{1da5d803-d492-4edd-8c23-e0c0ffee7f0e},0"

# https://learn.microsoft.com/en-us/windows/win32/api/mmdeviceapi/ne-mmdeviceapi-endpointformfactor
$formFactor = @(
    "RemoteNetworkDevice",
    "Speakers",
    "LineLevel",
    "Headphones",
    "Microphone",
    "Headset",
    "Handset",
    "UnknownDigitalPassthrough",
    "SPDIF",
    "DigitalAudioDisplayDevice",
    "UnknownFormFactor"
)

function getInternationalNameAndDriver($id) {
    $guid = $id.Substring(17)
    $subKey = @("Render","Capture")[[int]::Parse($id[5])]
    $reg = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\$subKey\$guid\Properties"
    $details = get-ItemProperty $reg -ea 0
    if ($details) {
        $id   = $details.$regId.subString(4)
        $name = $details.$regName
        $form = $formFactor[$details.$regFormFactor]

        $hardware = get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Enum\$id"
        $regDrv   = $hardware.Driver

        $driver   = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Class\$regDrv"
        $drvName    = $driver.DriverDesc
        $drvVersion = $driver.DriverVersion
    }
    return "$form ($name), driver: $drvName $drvVersion"
}
Run Code Online (Sandbox Code Playgroud)

这会给你这样的输出:

Default Speaker: Speakers (Realtek Audio), driver: Realtek Audio 6.0.1.6127
Default Micro  : Microphone (Logitech BRIO), driver: USB Audio Device 10.0.22000.653
Run Code Online (Sandbox Code Playgroud)