Powershell 可以监听和捕获按键吗?
是否可以编写一个 PowerShell 脚本,例如 AutoHotkey ,坐在托盘中并等待直到您按下预定义的键盘键开始执行?每次按下所述键时可能不会返回但会开火?
我想要实现的是 - 仅在启动脚本后按按钮执行预定义的脚本操作,因此将其放在桌面上并定义快捷键不起作用。
例如:
我希望每次按“x”键时输入 3 次文本“TEST”,但我希望只有在执行此操作的脚本正在运行时才会发生这种情况。因此,当脚本未运行时 - 按“x”将无济于事。
基本上,AutoHotkey 可以做到这一点,但如果可能的话,我想在 PowerShell 中做到这一点,而无需编写大量 C# 代码,因为那时我只需为此编写一个小型 C# 托盘应用程序。
最佳答案
可能不是直接在 PowerShell 中,但您几乎可以运行任何 C# 代码,这里是一个基于 excellent solution by Peter Hinchley 的基本工作示例:
Add-Type -TypeDefinition '
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace KeyLogger {
public static class Program {
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static HookProc hookProc = HookCallback;
private static IntPtr hookId = IntPtr.Zero;
private static int keyCode = 0;
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
public static int WaitForKey() {
hookId = SetHook(hookProc);
Application.Run();
UnhookWindowsHookEx(hookId);
return keyCode;
}
private static IntPtr SetHook(HookProc hookProc) {
IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
keyCode = Marshal.ReadInt32(lParam);
Application.Exit();
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
}
}
' -ReferencedAssemblies System.Windows.Forms
while ($true) {
$key = [System.Windows.Forms.Keys][KeyLogger.Program]::WaitForKey()
if ($key -eq "X") {
Write-Host "Do something now."
}
}
版本 2
(使用回调):
Add-Type -TypeDefinition '
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace PowerShell {
public static class KeyLogger {
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static Action<Keys> keyCallback;
private static IntPtr hookId = IntPtr.Zero;
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
public static void Run(Action<Keys> callback) {
keyCallback = callback;
hookId = SetHook();
Application.Run();
UnhookWindowsHookEx(hookId);
}
private static IntPtr SetHook() {
IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
return SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, moduleHandle, 0);
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {
var key = (Keys)Marshal.ReadInt32(lParam);
keyCallback(key);
}
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
}
}
' -ReferencedAssemblies System.Windows.Forms
[PowerShell.KeyLogger]::Run({
param($key)
if ($key -eq "X") {
Write-Host "Do something now."
}
})
关于powershell - 如何使用 PowerShell 捕获全局击键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54236696/