event-hook

justcoding121MIT活跃维护

跨平台 .NET 库,用来订阅 Windows、macOS、Linux 上的全局用户操作,包括键盘、鼠标、剪贴板、窗口、打印任务和热键,方便做行为监听类应用。

A .NET library to subscribe to global user actions on Windows, macOS, and Linux: keyboard, mouse, clipboard, application windows, print jobs, and hotkeys.

v3.0.0发布于 2026-09-08 14:01 UTC290star74fork同步于 2026-11-07 07:33 UTC

怎么上手

README 里没有找到可直接复制的安装命令

README 里没有找到可直接复制的安装命令,请到 README 或官方文档查看安装方式。

硬件要求

README 没有说明硬件要求。

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

这个项目的说明还在生成中,先参考下面「最近发版」和 README。

最近发版

5 个版本v3.0.0
  1. v3.0.0EventHook 3.0.0最新正式版2026-09-08 · 2026-09-08 14:01 UTC
  2. v3.0.0-beta.2EventHook 3.0.0-beta.2pre-release2026-09-08 · 2026-09-08 13:33 UTC
    查看更新说明
  3. v3.0.0-betaEventHook 3.0.0-betapre-release2026-09-08 · 2026-09-08 11:13 UTC
    查看更新说明
  4. v2.0.0EventHook 2.0.02026-09-07 · 2026-09-07 18:23 UTC
    查看更新说明

    Breaking

    • Targets net10.0-windows only (dropped .NET Framework 4.5). Existing 1.4.x consumers should stay on 1.4.113.

    Highlights

    • HotkeyWatcher
    • Mouse-move filter (IncludeMouseMove, #28)
    • Clipboard images/files
    • Dialog / MsgBox tracking and AppWindowFilter
    • PDF / virtual printers
    • x64/ARM64 P/Invoke pointer-size fixes
    • Reliable Stop / Dispose
    • GitHub Actions CI, DocFX, SonarCloud

    Full Changelog: https://github.com/justcoding121/windows-user-action-hook/compare/1.4.113...v2.0.0

  5. v2.0.0-betaEventHook 2.0.0-betapre-release2026-08-31 · 2026-08-31 12:56 UTC
    查看更新说明

    What's Changed

    New Contributors

    Full Changelog: https://github.com/justcoding121/windows-user-action-hook/compare/1.4.39...v2.0.0-beta

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    EventHook

    A .NET library to subscribe to global user actions across Windows, macOS, and Linux: keyboard, mouse, clipboard, application windows, print jobs, and hotkeys.

    CI NuGet NuGet downloads

    Install

    dotnet add package EventHook
    
    PlatformTarget framework
    Windowsnet10.0-windows
    macOS / Linuxnet10.0

    Windows applications must target net10.0-windows. The portable net10.0 package is for macOS and Linux.

    Sample

    using System;
    
    using (var eventHookFactory = new EventHookFactory())
    {
        var keyboardWatcher = eventHookFactory.GetKeyboardWatcher();
        var kb = keyboardWatcher.Start();
        if (!kb.Success)
        {
            Console.WriteLine(kb); // PermissionDenied / PrivilegeRequired / etc.
        }
        else
        {
            keyboardWatcher.OnKeyInput += (s, e) =>
                Console.WriteLine($"Key {e.KeyData.EventType} of {e.KeyData.Keyname}");
        }
    
        var mouseWatcher = eventHookFactory.GetMouseWatcher();
        mouseWatcher.IncludeMouseMove = false; // default is false
        mouseWatcher.Start().ThrowIfFailed();
        mouseWatcher.OnMouseInput += (s, e) =>
            Console.WriteLine($"Mouse {e.Message} at {e.Point.x},{e.Point.y}");
    
        var clipboardWatcher = eventHookFactory.GetClipboardWatcher();
        clipboardWatcher.Start().ThrowIfFailed();
        clipboardWatcher.OnClipboardModified += (s, e) =>
            Console.WriteLine($"Clipboard {e.DataFormat}: {e.Data}");
    
        var applicationWatcher = eventHookFactory.GetApplicationWatcher();
        applicationWatcher.Start().ThrowIfFailed();
        applicationWatcher.OnApplicationWindowChange += (s, e) =>
            Console.WriteLine($"{e.ApplicationData.AppName} was {e.Event}");
    
        var printWatcher = eventHookFactory.GetPrintWatcher();
        printWatcher.Start().ThrowIfFailed();
        printWatcher.OnPrintEvent += (s, e) =>
            Console.WriteLine($"Printer {e.EventData.PrinterName} pages={e.EventData.Pages}");
    
        var hotkeyWatcher = eventHookFactory.GetHotkeyWatcher();
        hotkeyWatcher.Start().ThrowIfFailed();
        hotkeyWatcher.Register("demo", new Hotkey(KeyModifiers.Control | KeyModifiers.Alt, EventKey.H))
            .ThrowIfFailed();
        hotkeyWatcher.OnHotkeyPressed += (s, e) =>
            Console.WriteLine($"Hotkey {e.Id} ({e.Hotkey})");
    
        Console.ReadLine();
    }
    

    OS hook callbacks only copy a lightweight snapshot and return immediately. Decoding and user event handlers run on a dedicated offload path so input is never blocked.

    Permissions and failures

    Start() / Register() return HookStartResult. Check Success, or call ThrowIfFailed(). IsRunning is true only after a successful install.

    ReasonTypical cause
    PermissionDeniedmacOS Input Monitoring / Accessibility (TCC)
    PrivilegeRequiredLinux /dev/input not readable (add user to input group)
    DisplayUnavailableNo DISPLAY / session when required (Linux/macOS). Not used for a missing Win32 pump.
    NotSupportedOnPlatformFeature needs X11 on Linux Wayland-only, or wrong TFM on Windows
    AlreadyInUseHotkey already registered by another process
    NativeFailureNative API failed after permissions were OK

    If EventHookFactory cannot start its own Windows message pump (or macOS cannot start its CFRunLoop), construction throws TimeoutException. That is not a HookStartResult — there is no HookFailureReason for “pump missing.”

    See examples/MAC.md and examples/LINUX.md for host setup.

    Message pump / event loop

    Hooks need an OS event loop. Callers usually do not create one: the factory (Windows) or platform hosts (macOS / Linux) start it.

    PlatformWho pumpsWhat you must do
    WindowsEventHookFactoryNothing in console/service code. Construct the factory on an STA UI thread or let it create a background STA WinForms loop (EventHook.MessagePump).
    macOSLibrary CFRunLoop (EventHook.Mac.CFRunLoop)Nothing. The HWND argument is ignored.
    Linux X11Library XNextEvent threadNeed DISPLAY (or Xvfb). HWND is ignored.
    Linux evdev/dev/input reads (no X loop)User must be in the input group. Clipboard / windows / hotkeys still need X11.

    Windows details

    • Keyboard and mouse (WH_KEYBOARD_LL / WH_MOUSE_LL) are installed on the factory pump thread. That thread must keep pumping or Windows stops delivering.
    • Clipboard (WM_CLIPBOARDUPDATE), hotkeys (WM_HOTKEY), and application/shell hooks are HWND messages on the same pump.
    • WindowHookEx does not use the factory pump. Call Start() from a thread that already pumps messages (your UI thread).
    • Hosted COM / Office add-ins: construct the factory on the STA UI thread, or pass that window’s HWND. A provided HWND must keep pumping. EventHook registers hotkeys on that handle but does not subclass it — if you pass a host HWND, your WndProc must dispatch WM_HOTKEY or the watcher will report IsRunning and still never fire.
    • Prefer the default new EventHookFactory() (library-owned pump) unless you are hosting and will forward messages.

    Application window filter (Windows)

    EventHook.Helpers.AppWindowFilter.IncludeWindowsWithoutSysMenu = true;
    EventHook.Helpers.AppWindowFilter.IncludeDialogs = true;
    EventHook.Helpers.AppWindowFilter.CustomFilter = hwnd => true;
    

    Hosted apps (COM / Office add-ins on Windows)

    Prefer constructing the factory on an STA UI thread, or pass an existing message-pump HWND:

    using var factory = new EventHookFactory(hostMainWindowHandle);
    

    Development

    • .NET 10 SDK
    • Windows: dotnet build src/Event.Hook.sln -c Release
    • Portable (macOS/Linux CI): build the library, tests, and console example projects (not the full Windows-only solution)
    • dotnet test tests/Event.Hook.Tests
    • dotnet test tests/Event.Hook.IntegrationTests
    • dotnet test tests/Event.Hook.E2ETests --filter Category=E2E
    • Docs: dotnet tool restore then docfx .github/docfx.json

    Release branches

    BranchNuGetNotes
    develop(no publish)CI on Windows + macOS + Linux; SonarCloud + DocFX on develop push only
    beta{VersionPrefix}-beta.2Same CI, then publish prerelease (3.0.0-beta already shipped)
    stable / tag v*{VersionPrefix}Same CI, then stable release + GitHub Pages docs

    Publishing uses NuGet Trusted Publishing (NUGET_USER on the nuget-publish environment).

    Version 3.0 notes

    Breaking: multi-platform (net10.0-windows + net10.0), Start()/Register() return HookStartResult, portable Hotkey replaces WinForms Keys, IncludeMouseMove defaults to false, non-blocking OS hook offload.

    Repository renamed from windows-user-action-hook to event-hook. Solution/projects use Event.Hook.*; NuGet package id remains EventHook.

    Code quality

    Quality Gate Coverage Lines of Code Bugs Vulnerabilities Code Smells Security Rating Reliability Rating Maintainability Rating Duplicated Lines Technical Debt