如何使用PowerShell捕获全局按键? [英] How to capture global keystrokes with PowerShell?
问题描述
Powershell可以侦听并捕获按键吗?
Can Powershell listen for and capture key presses?
是否可以编写一个PowerShell脚本,例如 AutoHotkey ,它位于托盘中并等待直到您按预定义的键盘键开始执行?可能每次您按下该键时都不会返回而是开火?
Is it possible to write a PowerShell script that, like AutoHotkey, sits in tray and waits until you press a predefined keyboard key to start execution? And possibly not return but fire every time you press said key?
我要实现的是-仅在启动脚本后按下按钮才能执行预定义的脚本操作,因此将其放在桌面上并定义快捷键是行不通的.
What I would like to achieve is - perform a predefined scripted action at the press of a button only AFTER starting the script, so putting it on the desktop and defining a shortcut key doesn't work.
例如:
我希望每次按"x"键时都要键入3次"TEST"文本,但是我希望只有在执行此操作的脚本正在运行时才会发生这种情况.因此,当脚本未运行时-按"x"将无济于事.
For example:
I'd like the text "TEST" typed 3 times every time I press the "x" key but I would like this to happen only if the script that does this is running. So when the script is not running - pressing "x" would do nothing.
基本上,AutoHotkey可以做到这一点,但是我想在PowerShell中尽可能地做到这一点,而无需编写大量的C#代码,因为那样的话,我将为此编写一个小型的C#托盘应用程序.
Basically, AutoHotkey can do exactly that but I'd like to do it in PowerShell, if possible, without writing huge amounts of C# code, because then I'd just write a tiny C# tray application for that.
推荐答案
也许不是直接在PowerShell中,但由于您几乎可以运行任何C#代码,因此以下是基于
Not in PowerShell directly maybe, but as you can run pretty much any C# code, here is a basic working example based on an 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捕获全局按键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!