Winapi 如何从PowerShell静音/取消静音

Winapi 如何从PowerShell静音/取消静音,winapi,powershell,volume,mute,Winapi,Powershell,Volume,Mute,正在尝试编写PowerShell cmdlet,该cmdlet将在开始时静音(除非已静音),并在结束时取消静音(仅当开始时未静音时)。 找不到任何可以使用的PoweShell或WMI对象。我曾尝试过使用Win32函数,比如or,但无法让它正常工作(如何从IntPtr读取值?) 我使用的是V2 CTP2。各位有什么想法吗 谢谢 只需管理Windows音频服务,您就可以用另一种方式剥猫皮。停止它以静音,启动它以取消静音。似乎没有一种快速简便的方法来调整音量。。如果您有C++经验,您可以做一些事情,在

正在尝试编写PowerShell cmdlet,该cmdlet将在开始时静音(除非已静音),并在结束时取消静音(仅当开始时未静音时)。 找不到任何可以使用的PoweShell或WMI对象。我曾尝试过使用Win32函数,比如or,但无法让它正常工作(如何从IntPtr读取值?)

我使用的是V2 CTP2。各位有什么想法吗


谢谢

只需管理Windows音频服务,您就可以用另一种方式剥猫皮。停止它以静音,启动它以取消静音。

似乎没有一种快速简便的方法来调整音量。。如果您有C++经验,您可以做一些事情,在其中Larry Osterman描述了如何从平台API调用IdioDooPositCube接口(对于Vista,XP可能会比我在一些搜索中发现的更困难)。p>
V2确实允许您编译内联代码(通过添加类型),因此这可能是一个选项。

我在PowerShell中找不到如何做到这一点,但有一个名为NirCmd的命令行实用程序可以通过运行以下命令来实现:

C:\utils\nircmd.exe mutexysvolume 2

NirCmd在此处免费提供:
在ps1 powershell脚本上使用以下命令:

$obj = new-object -com wscript.shell 
$obj.SendKeys([char]173)
vbscript中的解决方案:

Set WshShell = CreateObject("WScript.Shell")
For i = 0 To 50
  WshShell.SendKeys(chr(174))
  WScript.Sleep 100
Next

按键每次减少2个音量。

从Vista开始,您必须使用来控制系统音量。它是一个不支持自动化的COM API,因此需要从.NET和PowerShell使用大量样板文件

无论如何,下面的代码使您可以从PowerShell访问
[Audio]::Volume
[Audio]::Mute
属性。这也适用于可能有用的远程计算机。只需在PowerShell窗口中复制并粘贴代码

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

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
  // f(), g(), ... are unused COM method slots. Define these if you care
  int f(); int g(); int h(); int i();
  int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
  int j();
  int GetMasterVolumeLevelScalar(out float pfLevel);
  int k(); int l(); int m(); int n();
  int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
  int GetMute(out bool pbMute);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
  int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume 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 Audio {
  static IAudioEndpointVolume Vol() {
    var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
    IMMDevice dev = null;
    Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
    IAudioEndpointVolume epv = null;
    var epvid = typeof(IAudioEndpointVolume).GUID;
    Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
    return epv;
  }
  public static float Volume {
    get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
    set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
  }
  public static bool Mute {
    get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
    set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
  }
}
'@
使用示例:

PS C:\> [Audio]::Volume         # Check current volume (now about 10%)
0,09999999
PS C:\> [Audio]::Mute           # See if speaker is muted
False
PS C:\> [Audio]::Mute = $true   # Mute speaker
PS C:\> [Audio]::Volume = 0.75  # Set volume to 75%
PS C:\> [Audio]::Volume         # Check that the changes are applied
0,75
PS C:\> [Audio]::Mute
True
PS C:\>
如果您需要的话,还有更全面的.NET核心音频API包装器,但我不知道有一套PowerShell友好的cmdlet

附言似乎很聪明,但对我不起作用。

看看我的答案


我知道这不是PowerShell,但结合Michael和Diogo的答案,可以得到一行VBScript解决方案:

CreateObject("WScript.Shell").SendKeys(chr(173))
mute.vbs
中单击此按钮,您只需双击即可切换静音

  • 仍然可以在Windows 10(10586.104)中使用
  • 无需像使用PowerShell那样
    设置ExecutionPolicy

Alexandre的回答符合我的情况,但他的示例由于“var”名称空间的编译错误而无法运行。似乎较新/不同版本的.net可能会导致该示例不起作用。如果您发现收到编译错误,这是针对这些情况尝试的替代版本:

Add Type-Language CsharpVersion3-TypeDefinition@'
使用System.Runtime.InteropServices;
[Guid(“5CDF2C82-841E-4546-9722-0CF74078229A”),接口类型(ComInterfaceType.InterfaceSiunknown)]
接口IAudioEndpointVolume{
//f()、g()、…是未使用的COM方法插槽。如果需要,请定义这些插槽
int f();int g();int h();int i();
int SetMasterVolumeLevelScalar(float-fLevel,System.Guid-pguidEventContext);
int j();
int GetMasterVolumeLevelScalar(输出浮点级);
int k();int l();int m();int n();
int SetMute([marshallas(UnmanagedType.Bool)]Bool bMute,System.Guid pguidEventContext);
int GetMute(out bool pbMute);
}
[Guid(“D66063F-1587-4E43-81F1-B948E807363F”),接口类型(ComInterfaceType.InterfaceSiunknown)]
接口IMM设备{
int ACTIVE(参考系统Guid id、int clsCtx、int activationParams、out IAudioEndpointVolume aev);
}
[Guid(“A95664D2-9614-4F35-A746-DE8DB63617E6”),接口类型(ComInterfaceType.InterfaceIsIUnknown)]
接口IMMDeviceEnumerator{
int f();//未使用
int GetDefaultAudioEndpoint(int数据流、int角色、out-IMMDevice端点);
}
[ComImport,Guid(“BCDE0395-E52F-467C-8E3D-C4579291692E”)]类MMDeviceEnumerator对象{
公共类音频{
静态IAudioEndpointVol(){
var enumerator=新的MMDeviceEnumeratorComObject()作为IMMDeviceEnumerator;
immdev=null;
Marshal.ThroweExceptionForHR(枚举器.GetDefaultAudioEndpoint(/*eRender*/0,/*eMultimedia*/1,out dev));
IAudioEndpointVolume epv=null;
var epvid=typeof(IAudioEndpointVolume).GUID;
通过HR异常处理(开发激活(参考epvid,/*CLSCTX_ALL*/23,0,out epv));
返回epv;
}
公共静态浮动量{
获取{float v=-1;Marshal.throweexceptionforhr(Vol().GetMasterVolumeLevelScalar(out v));返回v;}
设置{Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value,System.Guid.Empty));}
}
公共静态布尔静音{
获取{bool mute;Marshal.throweexceptionforhr(Vol().GetMute(out mute));返回mute;}
设置{Marshal.ThrowExceptionForHR(Vol().SetMute(value,System.Guid.Empty));}
}
}
'@
用法相同:

PS C:\> [Audio]::Volume         # Check current volume (now about 10%)
0,09999999
PS C:\> [Audio]::Mute           # See if speaker is muted
False
PS C:\> [Audio]::Mute = $true   # Mute speaker
PS C:\> [Audio]::Volume = 0.75  # Set volume to 75%
PS C:\> [Audio]::Volume         # Check that the changes are applied
0,75
PS C:\> [Audio]::Mute
True
PS C:\>

在上面的第二个脚本中,要在第1行中使用PowerShell 7或PowerShell Core,请执行以下更改:

-Language CsharpVersion3

在W10上工作

请让我在得到一些关于我答案的反馈后再试一次

这是基于@frgnca的AudioDeviceCmdlet,可在此处找到:

下面是使每个录音设备静音的代码

Import-Module .\AudioDeviceCmdlets
$audio_device_list = Get-AudioDevice -list
$recording_devices = $audio_device_list | ? {$_.Type -eq "Recording"}
$recording_devices 
$recording_device_index = $recording_devices.Index | Out-String -stream
foreach ($i in $recording_device_index) {
    $inti = [int]$i
    Set-AudioDevice $inti | out-null -erroraction SilentlyContinue
    Set-AudioDevice -RecordingMute 1 -erroraction SilentlyContinue
}
导入AudioDeviceCmdlets dll,然后保存所有音频设备的列表,并向下过滤到录音设备中。您获取所有录音设备的索引,然后遍历每个设备,首先将该设备设置为主要音频设备,然后将该设备设置为静音(此两步过程是dll施加的限制)

要取消静音,请将-RecordingMute 1更改为RecordingMute 0

类似地,要使播放设备静音,可以使用以下代码:

Import-Module .\AudioDeviceCmdlets
$audio_device_list = Get-AudioDevice -list
$playback_devices = $audio_device_list | ? {$_.Type -eq "Playback"}
$playback_devices 
$playback_device_index = $playback_devices.Index | Out-String -stream
foreach ($i in $playback_device_index) {
$inti = [int]$i
    Set-AudioDevice $inti | out-null -erroraction SilentlyContinue
    Set-AudioDevice -PlaybackMute 1 -erroraction SilentlyContinue
}
要取消静音,请将-PlaybackMute 1更改为PlaybackMute 0

这段代码来自我的一个更大项目的一部分,该项目通过Arduino连接到一个物理按钮/LED静音状态显示,以启用sing
Import-Module .\AudioDeviceCmdlets
$audio_device_list = Get-AudioDevice -list
$recording_devices = $audio_device_list | ? {$_.Type -eq "Recording"}
$recording_devices 
$recording_device_index = $recording_devices.Index | Out-String -stream
foreach ($i in $recording_device_index) {
    $inti = [int]$i
    Set-AudioDevice $inti | out-null -erroraction SilentlyContinue
    Set-AudioDevice -RecordingMute 1 -erroraction SilentlyContinue
}
Import-Module .\AudioDeviceCmdlets
$audio_device_list = Get-AudioDevice -list
$playback_devices = $audio_device_list | ? {$_.Type -eq "Playback"}
$playback_devices 
$playback_device_index = $playback_devices.Index | Out-String -stream
foreach ($i in $playback_device_index) {
$inti = [int]$i
    Set-AudioDevice $inti | out-null -erroraction SilentlyContinue
    Set-AudioDevice -PlaybackMute 1 -erroraction SilentlyContinue
}