首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >确定windows当前是否正在播放声音。

确定windows当前是否正在播放声音。
EN

Stack Overflow用户
提问于 2017-07-31 17:48:45
回答 3查看 4.7K关注 0票数 12

所以我思考这个问题已经有一段时间了,我不知道该怎么做才是正确的。我想确定Windows是否在某个时候使用Powershell脚本输出声音。我可以确定音频驱动程序是否有错误,但我无法确定系统是否在播放声音。

我查看了用于.NETSystem.Media类,其中的三个类都与播放声音或操纵系统声音有关。

我不是要求为我编写代码,我只需要知道从哪里开始检查windows系统是否正在播放声音。

我有一个声音监视器,它在Node.js平台上连续地监视声音,当它失去声音时,它会发送给我一个文本。嗯,我还想让它通过它连接的所有系统,看看故障在哪里。这就是为什么我想看看windows电脑是否在播放声音。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-03 20:04:29

这里是如何使用西蒙·穆尔提供的代码。

运行下面的代码:

代码语言:javascript
运行
复制
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();

            // this is a bit tricky. 0 is the official "no sound" value
            // but for example, if you open a video and plays/stops with it (w/o killing the app/window/stream),
            // the value will not be zero, but something really small (around 1E-09)
            // so, depending on your context, it is up to you to decide
            // if you want to test for 0 or for a small value
            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
        }
    }
}
'@

我替换了所有var类型,因为这似乎解决了没有在PowerShell版本2上编译的代码的问题。

一旦加载,您就可以像这样检查状态:

代码语言:javascript
运行
复制
[Foo.Bar]::IsWindowsPlayingSound()
True or False

我在PowerShell 5.1上用Windows101703进行了测试

但也有一些警告:

代码语言:javascript
运行
复制
this is a bit tricky. 0 is the official "no sound" value
but for example, if you open a video and plays/stops with it (w/o killing the app/window/stream),
the value will not be zero, but something really small (around 1E-09)
so, depending on your context, it is up to you to decide
if you want to test for 0 or for a small value

因此,如果您将return value > 1E-08更改为return value > 0,则当视频暂停时,您将得到真。

票数 14
EN

Stack Overflow用户

发布于 2017-08-03 12:11:56

下面是一个示例C#代码,用于确定是否正在呈现任何音频流。它使用Windows (特别是IAudioMeterInformation接口),并在Vista和更高版本上得到支持。

代码语言:javascript
运行
复制
public static bool IsWindowsPlayingSound()
{
    var enumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
    var speakers = enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
    var meter = (IAudioMeterInformation)speakers.Activate(typeof(IAudioMeterInformation).GUID, 0, IntPtr.Zero);
    var value = meter.GetPeakValue();

    // this is a bit tricky. 0 is the official "no sound" value
    // but for example, if you open a video and plays/stops with it (w/o killing the app/window/stream),
    // the value will not be zero, but something really small (around 1E-09)
    // so, depending on your context, it is up to you to decide
    // if you want to test for 0 or for a small value
    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
}

正如我在评论中所说的,我还创建了一个开源c++项目,这是一个简单的无摩擦的零依赖控制台应用程序,可以在这里获得:https://github.com/smourier/IsWindowsPlayingSound。我添加了一个应该支持32位和64位的x86发布二进制OSes:https://github.com/smourier/IsWindowsPlayingSound/releases

您可以在PowerShell中使用它,就像任何外部.exe程序一样。它将返回一个可以使用标准方法检索的错误级别,例如:https://blogs.msdn.microsoft.com/powershell/2006/09/15/errorlevel-equivalent/

以下是等效的C++代码:

代码语言:javascript
运行
复制
  #include "stdafx.h" // includes <Endpointvolume.h> and <Mmdeviceapi.h>

  #define WIDEN2(x) L ## x
  #define WIDEN(x) WIDEN2(x)
  #define __WFILE__ WIDEN(__FILE__)
  #define HRCHECK(__expr) {hr=(__expr);if(FAILED(hr)){wprintf(L"FAILURE 0x%08X (%i)\n\tline: %u file: '%s'\n\texpr: '" WIDEN(#__expr) L"'\n",hr, hr, __LINE__,__WFILE__);goto cleanup;}}
  #define RELEASE(__p) {if(__p!=nullptr){__p->Release();__p=nullptr;}}

  int main(int argc, char *argv[])
  {
    BOOL playing = FALSE;
    BOOL loopmode = FALSE;
    float epsilon = 1E-07;
    float value = 0;
    HRESULT hr = S_OK;
    IMMDeviceEnumerator* pEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IAudioMeterInformation *pMeter = NULL;

    // Parse optional args
    // "loop" -> sets a loop mode for easy testing
    // <float value> -> changes epsilon
    for (int i = 1; i < argc; i++)
    {
      if (!strcmp(argv[i], "loop"))
      {
        loopmode = TRUE;
        continue;
      }

      float eps = atof(argv[i]);
      if (eps != 0.0)
      {
        epsilon = eps;
        continue;
      }
    }

    CoInitialize(NULL);
    HRCHECK(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator));
    HRCHECK(pEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &pDevice));
    HRCHECK(pDevice->Activate(__uuidof(IAudioMeterInformation), CLSCTX_ALL, NULL, (void**)&pMeter));
    do
    {
      HRCHECK(pMeter->GetPeakValue(&value));
      playing = value > epsilon;
      if (!loopmode)
        break;

      printf("%.10f playing:%i\n", value, playing);
      Sleep(100);
    } while (TRUE);

  cleanup:
    RELEASE(pMeter);
    RELEASE(pDevice);
    RELEASE(pEnumerator);
    CoUninitialize();
    if (FAILED(hr))
    {
      printf("An error occurred: 0x%08X\n", hr);
      return hr;
    }

    if (playing)
    {
      printf("Windows is playing a sound.\n");
    }
    else
    {
      printf("Windows is not playing a sound.\n");
    }
    return playing;
  }
票数 14
EN

Stack Overflow用户

发布于 2017-08-02 21:57:14

您可以使用由AudioDeviceCmdlets编写的克里斯·亨特模块

Write-DefaultAudioDeviceValue -StreamValue看起来就像你要找的东西。否则,您可以查看他的源代码,了解他如何使用CoreAudioApi提取这些值。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45422255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档