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

Tra*_*Guy 18 powershell winapi volume mute

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

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

谢谢!

Ale*_*min 22

从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)); }
  }
}
'@
Run Code Online (Sandbox Code Playgroud)

使用范例:

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:\>
Run Code Online (Sandbox Code Playgroud)

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

PS 迪奥戈的回答似乎很聪明,但它对我不起作用.


Dio*_*ogo 15

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

$obj = new-object -com wscript.shell 
$obj.SendKeys([char]173)
Run Code Online (Sandbox Code Playgroud)

  • 这是按下静音键的一种很好且简单的方法,但是它只是一个切换而不是离散静音。如果不知道卷的状态,它可能会做出与预期相反的事情。 (5认同)

Anc*_*ama 7

Alexandre的答案符合我的情况,但由于关于'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)); }
  }
}
'@
Run Code Online (Sandbox Code Playgroud)

用法是一样的:

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:\>
Run Code Online (Sandbox Code Playgroud)


小智 6

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

CreateObject("WScript.Shell").SendKeys(chr(173))
Run Code Online (Sandbox Code Playgroud)

将其放入mute.vbs,只需双击即可切换静音

  • 仍然适用于 Windows 10 (10586.104)
  • 不需要Set-ExecutionPolicy像使用 PowerShell 那样


Bri*_*ams 5

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


Ste*_*ski 5

似乎没有一种快速简便的方法来调整音量.如果你有c ++经验,你可以对这篇博文做点什么,其中Larry Osterman描述了如何从平台api调用IAudioEndpointVolume接口(对于Vista,从我在一些搜索中发现的内容来看,XP可能会更难.

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