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

C# PuppeteerSharp项目如何全局监听左右方向键按下并执行对应逻辑

解决方案

实现思路

因为你的需求是程序未聚焦时也能检测全局按键,普通控制台按键监听接口仅能响应程序聚焦时的输入,因此必须调用Windows底层的低级别键盘钩子(Low Level Keyboard Hook)API实现全局监听,PuppeteerSharp本身不提供跨窗口的全局按键检测能力。

完整实现代码

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using PuppeteerSharp;

namespace GoogleMapsChecker
{
    internal class Program
    {
        // 键盘钩子相关常量定义
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private const int VK_LEFT = 0x25;
        private const int VK_RIGHT = 0x27;
        
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        // 业务逻辑标记,避免按键重复触发,不需要连续触发可保留
        private static bool _isProcessing = false;

        private static async Task Main(string[] args)
        {
            // 注册全局键盘钩子
            _hookID = SetHook(_proc);

            try
            {
                // 原有PuppeteerSharp逻辑
                var browser = await Puppeteer.LaunchAsync(new LaunchOptions
                {
                    Headless = false,
                    ExecutablePath = @"C:\Program Files\Google\Chrome\Application\chrome.exe"
                });

                var page = await browser.NewPageAsync();
                var searchTerm = "searchTerm";

                await page.GoToAsync("https://www.google.ch/");
                await Task.Delay(5000);
                await page.ClickAsync(".gLFyf");
                await page.Keyboard.SendCharacterAsync(searchTerm);
                await page.Keyboard.PressAsync("Enter");

                Console.WriteLine("已就绪,按左/右方向键执行对应操作,按Q退出程序");
                // 保持程序运行不退出
                while (true)
                {
                    var key = Console.ReadKey(true);
                    if (key.Key == ConsoleKey.Q)
                    {
                        break;
                    }
                    await Task.Delay(100);
                }
            }
            finally
            {
                // 退出时卸载钩子,避免资源泄漏
                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 delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        // 钩子回调函数
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN && !_isProcessing)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                switch (vkCode)
                {
                    case VK_LEFT:
                        _isProcessing = true;
                        // 左方向键业务逻辑
                        Console.WriteLine("检测到左方向键按下");
                        _ = Task.Run(async () =>
                        {
                            try
                            {
                                // 此处替换为你的左按键业务逻辑
                                await Task.CompletedTask;
                            }
                            finally
                            {
                                _isProcessing = false;
                            }
                        });
                        break;
                    case VK_RIGHT:
                        _isProcessing = true;
                        // 右方向键业务逻辑
                        Console.WriteLine("检测到右方向键按下");
                        _ = Task.Run(async () =>
                        {
                            try
                            {
                                // 此处替换为你的右按键业务逻辑
                                await Task.CompletedTask;
                            }
                            finally
                            {
                                _isProcessing = false;
                            }
                        });
                        break;
                }
            }
            // 其他按键直接透传,不影响系统正常输入
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        // 导入Win32 API
        [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);
    }
}

注意事项

  • 该实现仅支持Windows系统,低级别键盘钩子是Windows平台专属API
  • 不需要限制单次按键触发的话可以删除_isProcessing相关逻辑
  • 所有非左右方向键的输入都会正常透传给系统,不会影响其他软件的正常使用

内容的提问来源于stack exchange,提问作者Nightscape

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 23:36:08