I am trying to find a way to detect if one specific program is playing sound. To make a long story short, the computers at my workplace all have a program called ReSoin.exe which should always be playing sound if it is functioning properly. If ReSoin is active but is not playing sound, I need to close and reopen ReSoin. I want to automate this process.
Using the method described by Persistent13 here and my very basic understanding of Powershell, I have created a loop to determine if a Windows machine is playing any sound. If Resoin is active and no sound is playing on the computer, the loop closes and reopens ReSoin.
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
namespace Foo
{
public class Bar
{
public static bool IsWindowsPlayingSound()
{
IMMDeviceEnumerator enumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
IMMDevice speakers = enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
IAudioMeterInformation meter = (IAudioMeterInformation)speakers.Activate(typeof(IAudioMeterInformation).GUID, 0, IntPtr.Zero);
float value = meter.GetPeakValue();
return value > 1E-08;
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
private class MMDeviceEnumerator
{
}
private enum EDataFlow
{
eRender,
eCapture,
eAll,
}
private enum ERole
{
eConsole,
eMultimedia,
eCommunications,
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
private interface IMMDeviceEnumerator
{
void NotNeeded();
IMMDevice GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role);
// the rest is not defined/needed
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D666063F-1587-4E43-81F1-B948E807363F")]
private interface IMMDevice
{
[return: MarshalAs(UnmanagedType.IUnknown)]
object Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams);
// the rest is not defined/needed
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064")]
private interface IAudioMeterInformation
{
float GetPeakValue();
// the rest is not defined/needed
}
}
}
'@
While(1) {
$ReSoinIsActive = Get-Process ReSoin -ErrorAction SilentlyContinue
if($ReSoinIsActive -ne $null) {
$ReSoinIsPlayingSounds = [Foo.Bar]::IsWindowsPlayingSound()
if($ReSoinIsPlayingSounds -eq $False) {
Stop-Process -Name "ReSoin" -Force
Start-Process -FilePath "C:\Program Files (x86)\ReLANpro\Cloud And Class Student\ReSoin.exe"
}else {
# Placeholder used for testing, please ignore
}
}else{
# Placeholder used for testing, please ignore
}
start-sleep -seconds 1
}
This is functional, but it has an obvious flaw. If any other program is playing noise, the computer will assume ReSoin is working. Is there a way to adapt this so that it will only detect if ReSoin is playing noise? I'm an amateur with Powershell and batch scripting, but I'm happy to try other scripting methods if anyone has another idea. If my goal is impossible to achieve, or too difficult to ask of the StackOverflow community, please let me know. Any help would be greatly appreciated.