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

时间:2008-11-01 02:11:18

标签: winapi powershell volume mute

尝试编写一个PowerShell cmdlet,它将在开始时静音,除非已经静音,并在结尾处取消静音(仅当它没有静音时才开始)。 找不到我可以使用的任何PoweShell或WMI对象。我正在使用像auxGetVolumeauxSetVolume这样的Win32函数,但却无法让它工作(如何从IntPtr中读取值?)。

我正在使用V2 CTP2。有什么想法吗?

谢谢!

12 个答案:

答案 0 :(得分:19)

从Vista开始,您必须使用Core Audio API来控制系统音量。它是一个不支持自动化的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:\>

如果您需要Core Audio API,还有更全面的.NET包装器,但我不知道有一组PowerShell友好的cmdlet。

P.S。 Diogo answer似乎很聪明,但它对我不起作用。

答案 1 :(得分:15)

在ps1 powershell脚本上使用以下命令:

$obj = new-object -com wscript.shell 
$obj.SendKeys([char]173)

答案 2 :(得分:7)

亚历山大的答案符合我的情况,但由于关于'var'命名空间的编译错误,他的例子不起作用。似乎较新/不同版本的.net可能导致该示例不起作用。如果您发现收到了编译错误,则可以尝试这种情况的替代版本:

Add-Type -Language CsharpVersion3 -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:\>

答案 3 :(得分:6)

如果可以do it in C#,您可以do it in PowerShell

答案 4 :(得分:5)

只需管理Windows音频服务,您就可以通过另一种方式为猫咪换肤。停止它静音,启动它取消静音。

答案 5 :(得分:5)

似乎没有快速简便的方法来调整音量。如果你有c ++经验,你可以用this blog post做一些事情,其中​​Larry Osterman描述了如何从平台调用IAudioEndpointVolume接口api(对于Vista,XP可能比我在一些搜索中发现的更难)。

V2允许您编译内联代码(通过Add-Type),因此这可能是一个选项。

答案 6 :(得分:2)

我没有在PowerShell中找到如何执行此操作,但是有一个名为NirCmd的命令行实用程序可以通过运行此命令来完成此操作:

C:\ utils \ nircmd.exe mutesysvolume 2

NirCmd在这里免费提供: http://www.nirsoft.net/utils/nircmd.html

答案 7 :(得分:2)

vbscript中的解决方案:

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

键每次减少2个音量。

答案 8 :(得分:2)

我知道它不是PowerShell,但结合Michael和Diogo的答案提供了单行VBScript解决方案:

CreateObject("WScript.Shell").SendKeys(chr(173))

mute.vbs中暂停此操作,您只需双击即可切换静音

  • 仍适用于Windows 10(10586.104)
  • 无需使用PowerShell
  • Set-ExecutionPolicy

答案 9 :(得分:1)

查看我对Change audio level from powershell?

的回答
Set-DefaultAudioDeviceMute

答案 10 :(得分:1)

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

这是基于 @frgnca 的 AudioDeviceCmdlets,在这里找到:https://github.com/frgnca/AudioDeviceCmdlets

这里是将所有录音设备静音的代码。

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,然后保存所有音频设备的列表,过滤到录音设备。您获取所有录音设备的索引,然后遍历每个设备,首先将该设备设置为您的主要音频设备,然后将该设备设置为静音(这 2 个步骤过程是 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 静音状态显示,以启用单按钮按下静音/取消静音所有系统麦克风(以帮助 Zoom、Meet、Teams、 Discord 等)并帮助人们避免尴尬的热话筒事件。

https://github.com/dakota-mewt/mewt

1

附言我真的很喜欢一些单行解决方案,例如 Change audio level from powershell?

但是,请注意,单线静音通常仅适用于当前设置为 Windows 默认的单个设备。因此,如果您的软件能够处理不同的音频设备(例如 Zoom 和 Meet),而它们碰巧使用的是非默认设备,则可能无法正常工作。

答案 11 :(得分:0)

在上面的第二个脚本中,要在第一行中的PowerShell 7或PowerShell Core中工作,请更改:

-Language CsharpVersion3

到...

-Language Csharp

正在研究W10