I'm trying to get the name of applications that are actively playing audio in Windows 11 using the NAudio library. I'm using the latest official precompiled NAudio.dll v.1.9 as I could not get it working with the latest nuget package 2.2.1. With this code I can get the playback devices info but the Audio Sessions are always empty.
Add-Type -Path "C:\NAudio.dll"
$devices = (New-Object -TypeName NAudio.CoreAudioApi.MMDeviceEnumerator).EnumerateAudioEndPoints([NAudio.CoreAudioApi.DataFlow]::Render, [NAudio.CoreAudioApi.DeviceState]::Active)
foreach ($device in $devices) {
Write-Host "Device: $($device.FriendlyName)"
$sessions = $device.AudioSessionManager2.Sessions
Write-Host "Number of sessions: $($sessions.Count)"
foreach ($session in $sessions) {
Write-Host "Session: $($session.DisplayName)"
Write-Host "Is Muted: $($session.SimpleAudioVolume.Mute)"
Write-Host "Volume: $($session.SimpleAudioVolume.Volume)"
}
}
Terminal output:
Device: Sound Blaster Z (Sound Blaster Z)
Number of sessions: 0
I did read the questions where people were able to get audio sessions using C# but I was hoping to be able to do the same in PowerShell.
The reason why downloading the latest package from Nuget didn't work for you is because the NAudio
Package has a bunch of dependencies (including the NAudio.CoreAudioApi
Namespace, where the MMDeviceEnumerator
Class exists).
Specifically, the MMDeviceEnumerator
class exists in NAudio.Wasapi
Pacakage:
PS ..\pwsh> [NAudio.CoreAudioApi.MMDeviceEnumerator].Assembly
Version Name PublicKeyToken Target Culture
------- ---- -------------- ------ -------
2.2.1.0 NAudio.Wasapi e279aa5131008a41 MSIL neutral
Ideally, Install-Package
should be able to handle dependencies for you (unsure on this, my experience with this cmdlet is really bad - see other option using the dotnet
CLI below):
Install-Package NAudio -Version 2.2.1
Another option to download the assemblies is to use the dotnet CLI, available when installing the .NET SDK. I personally use this:
try {
$framework = 'netstandard2.0'
$packagename = 'NAudio'
dotnet new classlib -f $framework -o "$packagename.package"
Push-Location "$packagename.package"
dotnet add package $packagename
dotnet publish --configuration Release -o lib
}
finally {
Pop-Location
}
You should have all required assemblies after:
Lastly, using the 2.2.1
version of this package, the following code should list all processes using an audio device.
try {
Add-Type -Path .\NAudio.package\lib\*.dll
$deviceEnumerator = [NAudio.CoreAudioApi.MMDeviceEnumerator]::new()
$audioEndPoints = $deviceEnumerator.EnumerateAudioEndPoints(
[NAudio.CoreAudioApi.DataFlow]::Render,
[NAudio.CoreAudioApi.DeviceState]::Active)
$result = $audioEndPoints | ForEach-Object {
$sessions = $_.AudioSessionManager.Sessions
for ($i = 0; $i -lt $sessions.Count; $i++) {
$session = $sessions[$i]
# Idle process, we can skip this
if ($session.GetProcessID -eq 0) {
continue
}
[pscustomobject]@{
Device = $_.FriendlyName
ProcessId = $session.GetProcessID
ProcessDisplayName = (Get-Process -Id $session.GetProcessID).ProcessName
State = $session.State
IsMuted = $session.SimpleAudioVolume.Mute
Volume = $session.SimpleAudioVolume.Volume
}
$session.Dispose()
}
$_.Dispose()
}
}
finally {
if ($deviceEnumerator) {
$deviceEnumerator.Dispose()
}
}
# Here is the output:
$result
You could filter this output for those objects where the .State
property is equal to AudioSessionState.AudioSessionStateActive
to find only those processes reproducing audio at the moment.
$result | Where-Object {
$_.State -eq [NAudio.CoreAudioApi.Interfaces.AudioSessionState]::AudioSessionStateActive
}