尝试编写一个PowerShell cmdlet,以在启动时静音(仅当未静音时),并在结束时解除静音(仅当开始时没有被静音)。
无法找到任何可用的PoweShell或WMI对象。我在玩Win32函数,如auxGetVolume或auxSetVolume,但无法完全使其工作(如何从IntPtr读取值?)。
我正在使用V2 CTP2。有什么建议吗?
谢谢!
尝试编写一个PowerShell cmdlet,以在启动时静音(仅当未静音时),并在结束时解除静音(仅当开始时没有被静音)。
无法找到任何可用的PoweShell或WMI对象。我在玩Win32函数,如auxGetVolume或auxSetVolume,但无法完全使其工作(如何从IntPtr读取值?)。
我正在使用V2 CTP2。有什么建议吗?
谢谢!
从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的回答似乎很聪明,但对我来说不起作用。
使用以下命令在ps1 powershell脚本上:
$obj = new-object -com wscript.shell
$obj.SendKeys([char]173)
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)); }
}
}
'@
使用方法相同:
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:\>
enumerator.GetDefaultAudioEndpoint
的第一个参数从 0
(eRender) 改为 1
(eCapture),那么这个代码就可以静音/取消静音默认的麦克风/输入设备。 - sparrowt您可以通过简单地管理Windows音频服务来实现另一种方法。停止它以静音,启动它以取消静音。
虽然这不是PowerShell,但将Michael和Diogo的答案结合起来可以得到一个一行的VBScript解决方案:
CreateObject("WScript.Shell").SendKeys(chr(173))
将以下内容复制到mute.vbs
文件中,双击即可切换静音状态:
Set-ExecutionPolicy
Vbscript解决方案:
Set WshShell = CreateObject("WScript.Shell")
For i = 0 To 50
WshShell.SendKeys(chr(174))
WScript.Sleep 100
Next
这些按键每按一次就会将音量缩小2。
我在PowerShell中没有找到如何做到这一点,但是有一个命令行实用程序叫做NirCmd,可以通过运行以下命令来实现:
C:\utils\nircmd.exe mutesysvolume 0 # 1 to to unmute, 2 to toggle
在得到一些反馈后,让我再试一次我的答案
这是基于@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
}
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
}
https://github.com/dakota-mewt/mewt
附言:我真的很喜欢一些单行解决方案,比如如何从powershell更改音频级别?
但是请注意,单行静音通常仅适用于当前设置为Windows默认值的单个设备。因此,如果您有能够使用不同音频设备(如Zoom和Meet)的软件,并且它们恰好正在使用非默认设备,则可能无法按预期工作。