gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 23:49:55 27 4
gpt4 key购买 nike

我一直在尝试使用 powershell 4.0 获取音频信息,特别是声音播放时的峰值音频。所以我为核心音频 api 找到了一个 .Net 包装器(可以找到 here 并且 .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 列表中。但是,当然,由于最初的问题是 New-Object re an error on CoreAudio.AudioPeakMeter,powershell 甚至不会尝试访问这两个成员。

后一个命令返回 this我已经发布到pastebin。

方法属性 IsSecurityCritical 让我觉得我需要以提升的权限运行 powershell。但是,情况似乎并非如此,因为它没有任何区别。

我已经确认这些结果对于程序集中的所有类都是相同的。我可以访问枚举器。这是一个例子:
[enum]::GetNames([CoreAudio.DEVICE_STATE])  

这将正确返回 CoreAudio.DEVICE_STATE 的所有可能值。

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

最佳答案

找到了解决方案!这不完全是我正在寻找的解决方案,但它确实有效。我做了更多研究,发现 this post.似乎核心音频 api 的 .net 包装器根本无法与 powershell 配合使用。我最终查看了该问题的一个答案,弄清楚它是如何工作的,并对其进行修改以做我需要的事情。更多地探索api,我发现我无论如何都试图使用错误的接口(interface)。我需要使用 IAudioMeterInformation而不是 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 之间的 float 变量,因此我将该值乘以 100 并将其转换为整数以将值四舍五入为最接近的整数。当检测到按键时循环结束。
do
{
Start-Sleep -Milliseconds 100
$var = [AudioMeter]::PeakValue * 100
$var
}
until($Host.UI.RawUI.KeyAvailable)
$Host.UI.RawUI.FlushInputBuffer()

我还没有弄清楚如何使用 IMMDevice::Activate()同时在多个接口(interface)上的方法,所以我可以使用 IAudioEndpointVolume以及访问 Mute方法,但这可能是不同日子的不同主题。

关于.net - powershell中.net框架对象的构造函数/方法问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26109552/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com