首页 > 解决方案 > Powershell 可以检测特定程序当前是否正在播放声音吗?

问题描述

我试图找到一种方法来检测一个特定的程序是否正在播放声音。长话短说,我工作场所的计算机都有一个名为 ReSoin.exe 的程序,如果它运行正常,它应该始终播放声音。如果 ReSoin 处于活动状态但没有播放声音,我需要关闭并重新打开 ReSoin。我想自动化这个过程。

使用 Persistent13 here描述的方法和我对 Powershell 的非常基本的了解,我创建了一个循环来确定 Windows 机器是否正在播放任何声音。如果 Resoin 处于活动状态并且计算机上没有播放声音,则循环关闭并重新打开 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
}

这是功能性的,但它有一个明显的缺陷。如果任何其他程序正在播放噪音,计算机将假定 ReSoin 正在工作。有没有办法调整它,以便它只检测 ReSoin 是否在播放噪音?我是 Powershell 和批处理脚本的业余爱好者,但如果有人有其他想法,我很乐意尝试其他脚本方法。如果我的目标无法实现,或者向 StackOverflow 社区提问太难,请告诉我。任何帮助将不胜感激。

标签: powershellaudio

解决方案


推荐阅读