You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell 7中ReadKey()无法跨窗口追踪按键的替代方案咨询

PowerShell 7全局按键追踪的替代方案

我编写了一段用于追踪按键按下与释放的简单PowerShell脚本:

$j = 0
while($j -lt 10000){
    $PressedKey = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp")
    $PressedKey
    continue
}

运行该脚本时,在当前窗口内按键可正常输出结果,但切换到其他窗口或进程实例后,就无法再追踪按键并输出。请问有哪些可替代ReadKey()的方案,能实现跨窗口/实例的按键追踪?我使用的是PowerShell 7。

可行的替代方案

1. 调用Windows API实现全局钩子

PowerShell本身没有原生的全局按键捕获能力,但可以通过调用Win32 API的全局键盘钩子来实现。以下是一个示例脚本,通过Add-Type封装必要的API函数:

Add-Type @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class GlobalKeyHook
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;

    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    public static void StartHook()
    {
        _hookID = SetHook(_proc);
        Application.Run();
    }

    public static void StopHook()
    {
        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_KEYUP))
        {
            int vkCode = Marshal.ReadInt32(lParam);
            string keyState = wParam == (IntPtr)WM_KEYDOWN ? "按下" : "释放";
            Console.WriteLine($"按键: {(Keys)vkCode} - {keyState}");
        }
        return CallNextHookEx(_hookID, nCode, wParam, IntPtr.Zero);
    }
}
"@ -ReferencedAssemblies System.Windows.Forms

# 启动全局钩子
[GlobalKeyHook]::StartHook()

# 按Ctrl+C停止钩子
try {
    while ($true) { Start-Sleep 1 }
}
finally {
    [GlobalKeyHook]::StopHook()
}

注意:这个脚本需要以管理员权限运行,因为全局钩子需要系统级权限;另外,PowerShell 7中需先确保安装System.Windows.Forms组件(可通过Install-Package System.Windows.Forms安装)。

2. 使用第三方PowerShell模块

社区中有专门用于全局按键监听的PowerShell模块,比如GlobalHotkey模块(需从PowerShell Gallery安装):

# 安装模块(首次运行)
Install-Module -Name GlobalHotkey -Scope CurrentUser -Force

# 导入模块
Import-Module GlobalHotkey

# 注册全局按键监听
Register-HotKey -Key "A" -Action { Write-Host "按键A被按下" }
Register-HotKey -Key "B" -KeyState Up -Action { Write-Host "按键B被释放" }

# 保持脚本运行以监听按键
while ($true) { Start-Sleep 1 }

这类模块封装了底层API,使用起来更简洁,无需自行编写钩子逻辑。

3. 借助AutoHotkey脚本

如果不想直接处理复杂的API调用,可以借助AutoHotkey的全局按键监听能力,让PowerShell调用AHK脚本并获取输出:

  1. 编写AHK脚本(KeyListener.ahk):
#Persistent
OnMessage(0x0100, "KeyDown")
OnMessage(0x0101, "KeyUp")
return

KeyDown(wParam, lParam) {
    FileAppend, 按下: %wParam%`n, *
}

KeyUp(wParam, lParam) {
    FileAppend, 释放: %wParam%`n, *
}
  1. 在PowerShell中运行AHK脚本并捕获输出:
# 假设AHK已安装在默认路径
Start-Process -FilePath "C:\Program Files\AutoHotkey\AutoHotkey.exe" -ArgumentList "KeyListener.ahk" -RedirectStandardOutput "key_log.txt" -NoNewWindow

# 实时读取日志文件
Get-Content "key_log.txt" -Wait

这种方案适合快速实现全局按键监听,且无需深入Win32 API的场景。

内容的提问来源于stack exchange,提问作者A Not Person

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:21:55