Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
powershell中.net framework对象的构造函数/方法问题_.net_Powershell_Audio - Fatal编程技术网

powershell中.net framework对象的构造函数/方法问题

powershell中.net framework对象的构造函数/方法问题,.net,powershell,audio,.net,Powershell,Audio,我一直在尝试使用powershell 4.0获取音频信息,特别是声音播放时的峰值音频。所以我找到了一个核心音频api的.Net包装器(可以找到,.dll位于CoreAudio\bin中),并且一直在尝试使用它。然而,就我的一生而言,我不知道如何做到这一点。主要的问题是我还没有弄清楚访问和使用程序集中包含的类的方法的语法。具体来说,我正在尝试使用CoreAudio.AudioPeakMeter和CoreAudio.AudioMute 例如,CoreAudio.AudioPeakMeter应该有两个

我一直在尝试使用powershell 4.0获取音频信息,特别是声音播放时的峰值音频。所以我找到了一个核心音频api的.Net包装器(可以找到,.dll位于CoreAudio\bin中),并且一直在尝试使用它。然而,就我的一生而言,我不知道如何做到这一点。主要的问题是我还没有弄清楚访问和使用程序集中包含的类的方法的语法。具体来说,我正在尝试使用CoreAudio.AudioPeakMeter和CoreAudio.AudioMute

例如,CoreAudio.AudioPeakMeter应该有两个成员:GetChannelCount和GetLevel

我试过使用

[CoreAudio.AudioPeakMeter] | Get-Member -Static
但这只返回Equals和ReferenceEquals,当我使用

[CoreAudio.AudioPeakMeter]::
我甚至发现有人在网上发布了一个检索构造函数的函数。这又一次没有任何结果。实际上什么都没有。不返回任何输出。我确认这对其他人有效,例如System.Windows.Thickness,这是文章中使用的一个示例

如果您感兴趣,这里是我找到的Get Contstructor函数

function get-Constructor ([type]$type, [Switch]$FullName)
{
    foreach ($c in $type.GetConstructors())
    {
        $type.Name + "("
        foreach ($p in $c.GetParameters())
        {
             if ($fullName)
             {
                  "`t{0} {1}," -f $p.ParameterType.FullName, $p.Name 
             }else
             {
                  "`t{0} {1}," -f $p.ParameterType.Name, $p.Name 
             }
        }
        ")"
    }
}
但是,我知道GetChannelCount和GetLevel是存在的,可以通过ISE找到

(New-Object CoreAudio.AudioPeakMeter).GetChannelCount
以及使用命令

[CoreAudio.AudioPeakMeter].GetMethods()
对于ISE,在输入时段后,GetChannelCount和GetLevel将填充到ISE列表中。但当然,由于最初的问题是CoreAudio.AudioPeakMeter上的新对象错误,powershell甚至不尝试访问这两个成员

后一个命令返回我发布到pastebin的内容

method属性IsSecurity Critical使我认为需要以提升的权限运行powershell。然而,情况似乎并非如此,因为这没有什么不同

我已经确认这些结果对于程序集中的所有类都是相同的。不过我可以访问枚举器。下面是一个例子:

[enum]::GetNames([CoreAudio.DEVICE_STATE])  
这将正确返回CoreAudio.DEVICE_状态的所有可能值


有什么我遗漏的吗?据我所知,程序集已正确加载(我使用了Add Type),但powershell表示,即使类方法存在,它们也不存在。

找到了解决方案!这并不完全是我所寻找的解决方案,但它是有效的。我做了更多的研究,发现核心音频api的.net包装器似乎不能很好地与powershell配合使用。最后,我看了一下这个问题的一个答案,弄清楚它是如何工作的,并修改它以满足我的需要。再仔细研究一下api,我发现我试图使用错误的接口。我需要使用
iaudiopemeterinformation
而不是
IAudioPeakMeter

以下是我想出的有效方法:

Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;

[Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioMeterInformation {
  int GetPeakValue(out float pfPeak);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
  int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioMeterInformation aev);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
  int f(); // Unused
  int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }

public class AudioMeter {
  static IAudioMeterInformation Meter() {
    var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
    IMMDevice dev = null;
    Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
    IAudioMeterInformation epv = null;
    var epvid = typeof(IAudioMeterInformation).GUID;
    Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
    return epv;
  }
  public static float PeakValue {
    get {float mv = -1; Marshal.ThrowExceptionForHR(Meter().GetPeakValue(out mv)); return mv;}
  }
}    
'@
现在,我可以检索音频设备的峰值,并通过循环流传输该值。峰值是一个从0到1的浮动变量,因此我将该值乘以100,并将其转换为整数,以将该值四舍五入到最接近的整数。当检测到按键时,循环结束

do
{
    Start-Sleep -Milliseconds 100
    $var = [AudioMeter]::PeakValue * 100
    $var
}
until($Host.UI.RawUI.KeyAvailable)
$Host.UI.RawUI.FlushInputBuffer()

我还没有弄清楚如何在多个接口上同时使用
IMMDevice::Activate()
方法,这样我就可以使用
IAudioEndpointVolume
以及访问
Mute
方法,但对于不同的一天,这可能是不同的主题

AudioPeakMeter
类没有公共构造函数。看起来有公共构造函数的少数类之一是
MMDeviceEnumerator
。我会从那里开始。您可能会从阅读附带的示例中获得更多信息。我对C#(或任何版本的C)的了解非常有限,因此我正在尽可能地理解源代码和示例,但仍然不够。据我所知和我的研究,AudioPeakMeter似乎有公共构造函数,但Powershell似乎无法看到它们。我还注意到
[CoreAudio.AudioPeakMeter]::GetChannelCount
运行时没有错误,但没有返回值。从源代码中,它应该返回一个int。