In a Powershell script, Mute is performed with:
(New-Object -ComObject WScript.Shell).SendKeys([char]173)
That works.
Windows reference lists constants for each key. Mute constant is VK_VOLUME_MUTE.
Is there some way to use VK_VOLUME_MUTE in the above Powershell command, instead of 173?
I tried key(VK_VOLUME_MUTE) and VkKeyScan(VK_VOLUME_MUTE), but I couldn't get them to work.
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscana
This question appears to be a different question, and there's no applicable answer.
2 Answers 2
If you want to get volume mute, this returns it. However, I don't see a reason you cannot just declare the constant.
# Check if System.Windows.Forms is already loaded
if (-not ("System.Windows.Forms" -in [AppDomain]::CurrentDomain.GetAssemblies().FullName)) {
Add-Type -AssemblyName System.Windows.Forms
}
# Get VK_VOLUME_MUTE value
$volumeMute = [int][System.Windows.Forms.Keys]::VolumeMute
echo $volumeMute
6 Comments
(New-Object -ComObject WScript.Shell).SendKeys(), you need a [char] rather than an [int] cast, as shown in the question (in Windows PowerShell, the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and final version is 5.1, you need [string] [char]). Also, it's simpler to just use Add-Type -AssemblyName System.Windows.Forms unconditionally: if the assembly is already loaded, the statement is a fast and quiet no-op.The VK_* (virtual-key code) constants are defined in the C/C++ Winuser.h preprocessor file and are therefore not directly available in PowerShell.
However, they are available via the WinForms .NET API, specifically via the [System.Windows.Forms.Keys] enum-derived type, whose symbolic names correspond to the VK_* constants as follows:[1]
- Pascal-casing the
VK_*constants without theirVK_prefix yields the corresponding[System.Windows.Forms.Keys]enumeration value;
e.g.,VK_VOLUME_MUTEcorresponds to[System.Windows.Forms.Keys]::VolumeMute.
That said, the type of interest requires first loading the WinForms assembly, System.Windows.Forms; given that this assembly is not strictly necessary to use the COM-based (New-Object -ComObject WScript.Shell).SendKeys() API,[2] this added overhead may or may not be acceptable; in terms of runtime cost (additional execution time), it is negligible, however.
Here's a complete example that works in both PowerShell editions (in both Windows PowerShell - the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and final version is 5.1 - as well as in PowerShell (Core) 7, the modern, cross-platform, install-on-demand edition):
# Allow accessing the WinForm types by type (class) name only.
# Note: Syntactically, `using` statements must come first in a script.
using namespace System.Windows.Forms
# Make sure the WinForms assembly is loaded.
# Note: If the assembly is already loaded, this is a fast and quiet no-op.
Add-Type -AssemblyName System.Windows.Forms
# Note: In *PowerShell 7* you may omit [string]
(New-Object -ComObject WScript.Shell).SendKeys([string] [char] [Keys]::VolumeMute)
Note the use of Add-Type -AssemblyName to load the well-known WinForms assembly.
While alternative use of a using assembly statement (using assembly System.Windows.Forms) should work (and does in Windows PowerShell), sadly it doesn't in PowerShell 7, up to at least v7.5.x, due to a well-known bug - see GitHub issue #11856.
[1] Seemingly, not all VK_* constants have WinForms counterparts, such as the VK_GAMEPAD_* ones.
[2] Note that the WinForms API too supports sending keystrokes in principle, via the [System.Windows.Forms.SendKeys] class, but sending virtual-key codes this way is not supported.
6 Comments
[string] cast.
VK_VOLUME_MUTEare pre-defined only for C/C++ code, not for scripts. Have a look at this question for using constants in Powershell (hint: it's not simple!).charconstants in C# and thenAdd-Typeit.... an easy way to start:public static class VirtualKeyCodes { public const char VK_VOLUME_MUTE = (char)0xAD; ... }then from pwsh you can$shell.SendKeys([VirtualKeyCodes]::VK_VOLUME_MUTE)for example. The powershell concept of constants is just nonsense garbage.