SharpHook 8.0.0
dotnet add package SharpHook --version 8.0.0
NuGet\Install-Package SharpHook -Version 8.0.0
<PackageReference Include="SharpHook" Version="8.0.0" />
<PackageVersion Include="SharpHook" Version="8.0.0" />
<PackageReference Include="SharpHook" />
paket add SharpHook --version 8.0.0
#r "nuget: SharpHook, 8.0.0"
#:package SharpHook@8.0.0
#addin nuget:?package=SharpHook&version=8.0.0
#tool nuget:?package=SharpHook&version=8.0.0
SharpHook
SharpHook provides a cross-platform global keyboard and mouse hook, event simulation, and text entry simulation for .NET. It is a wrapper of libuiohook and provides direct access to its features as well as higher-level types to work with it.
Usage
Global Hooks
SharpHook provides the IGlobalHook interface along with three default implementations which you can use to control the
hook and subscribe to its events. Here's a basic usage example:
using SharpHook;
var hook = new EventLoopGlobalHook();
// Events of type EventHandler<HookEventArgs>:
hook.HookEnabled += OnHookEnabled;
hook.HookDisabled += OnHookDisabled;
// Events of type EventHandler<KeyboardHookEventArgs>:
hook.KeyTyped += OnKeyTyped; // Disabled by default
hook.KeyPressed += OnKeyPressed;
hook.KeyReleased += OnKeyReleased;
// Events of type EventHandler<MouseHookEventArgs>:
hook.MouseClicked += OnMouseClicked;
hook.MousePressed += OnMousePressed;
hook.MouseReleased += OnMouseReleased;
hook.MouseMoved += OnMouseMoved;
hook.MouseMovedRelative += OnMouseMovedRelative;
hook.MouseDragged += OnMouseDragged;
hook.MouseDraggedRelative += OnMouseDraggedRelative;
// Events of type EventHandler<MouseWheelHookEventArgs>:
hook.MouseWheel += OnMouseWheel;
hook.Run();
// or
await hook.RunAsync();
First, you create the hook, then subscribe to its events, and then run it. The Run method runs the hook on the current
thread, blocking it. The RunAsync() method runs the hook on a separate thread and returns a Task which is finished
when the hook is stopped. You can subscribe to events after the hook is started.
IGlobalHook contains the Stop method to stop the global hook. After stopping, the global hook can be started again
by calling the Run or RunAsync method. Calling Stop when the hook is not running won't do anything.
IGlobalHook extends IDisposable. When you call the Dispose method on a hook, it's disposed and stopped if it was
running. Once a hook has been disposed, it cannot be started again – you'll have to create a new instance. Calling
Dispose when the hook is not running won't do anything other than marking the instance as disposed.
Hook events are of type HookEventArgs or a derived type which contains more info. It's possible to suppress event
propagation by setting the SuppressEvent property to true inside the event handler. This must be done synchronously
and is only supported on Windows and macOS. You can check the event time and whether the event is real or simulated with
the EventTime and IsEventSimulated properties respectively.
Important: Always use one instance of
IGlobalHookat a time in the entire application since they all must use the same static method to set the hook callback for libuiohook, so there may only be one callback at a time. Running a global hook when another global hook is already running will corrupt the internal global state of libuiohook.
You can create a keyboard-only or a mouse-only hook by passing a GlobalHookType to Run or RunAsync. On Windows,
there are two different global hooks – a keyboard hook and a mouse hook. On macOS and Linux, there is one hook for all
events, and this enables filtering keyboard or mouse events out on these OSes, though on Wayland, the connection to the
compositor will be established only if mouse events are enabled since they need to know the screen size and bounds.
On Wayland, absolute mouse position is usually not available, so you should subscribe to the MouseMovedRelative and
MouseDraggedRelative in addition to MouseMoved and MouseDragged if you want to listen to mouse movement. On other
platforms, relative motion events are never raised.
SharpHook provides three implementations of IGlobalHook:
SharpHook.SimpleGlobalHookruns all of its event handlers on the same thread on which the hook itself runs. This means that the handlers should generally be fast since they will block the hook from handling the events that follow if they run for too long.SharpHook.EventLoopGlobalHookruns all of its event handlers on a separate dedicated thread. On backpressure it will queue the remaining events which means that the hook will be able to process all events. This implementation should be preferred toSimpleGlobalHookexcept for very simple use-cases. But it has a downside – suppressing event propagation will be ignored since event handlers are executed on another thread.SharpHook.TaskPoolGlobalHookruns all of its event handlers on other threads inside the default thread pool for tasks. The parallelism level of the handlers can be configured. On backpressure it will queue the remaining events which means that the hook will be able to process all events. Like withEventLoopGlobalHook, suppressing event propagation will be ignored since event handlers are executed on other threads. In general,EventLoopGlobalHookshould be preferred instead, as this class provides benefits only if events should be processed in parallel, which is rarely the case.
The library also provides the SharpHook.GlobalHookBase class which you can extend to create your own implementation
of the global hook. It calls the appropriate event handlers, and you only need to implement a strategy for dispatching
the events. It also keeps a reference to a running global hook so that it's not garbage-collected.
The library also provides the IBasicGlobalHook interface and the BasicGlobalHookBase class. This class can be
extended to create a custom global hook which has a different form of events from that in IGlobalHook.
Reactive Global Hooks
Use the SharpHook.Reactive package for reactive global hooks with the Rx.NET integration.
Use the SharpHook.ReactiveUI package for reactive global hooks with the ReactiveUI.Primitives integration.
Use the SharpHook.R3 package for reactive global hooks with the R3 integration.
Event Simulation
SharpHook provides the ability to simulate keyboard and mouse events in a cross-platform way as well. Here's a quick example:
using SharpHook;
using SharpHook.Data;
using var simulator = EventSimulator.Create("Your application name");
// Press Ctrl+C
simulator.SimulateKeyPress(KeyCode.VcLeftControl);
simulator.SimulateKeyPress(KeyCode.VcC);
// Release Ctrl+C
simulator.SimulateKeyRelease(KeyCode.VcC);
simulator.SimulateKeyRelease(KeyCode.VcLeftControl);
// Simulate pressing Ctrl, then pressing C, then releasing C, then releasing Ctrl
simulator.SimulateKeyStroke(KeyCode.VcLeftControl, KeyCode.VcC);
// Press the left mouse button
simulator.SimulateMousePress(MouseButton.Button1);
// Release the left mouse button
simulator.SimulateMouseRelease(MouseButton.Button1);
// Press the left mouse button at (0, 0)
simulator.SimulateMousePress(0, 0, MouseButton.Button1);
// Release the left mouse button at (0, 0)
simulator.SimulateMouseRelease(0, 0, MouseButton.Button1);
// Move the mouse pointer to (0, 0)
simulator.SimulateMouseMovement(0, 0);
// Move the mouse pointer 50 pixels to the right and 100 pixels down
simulator.SimulateMouseMovementRelative(50, 100);
// Scroll the mouse wheel
simulator.SimulateMouseWheel(
rotation: -120,
direction: MouseWheelScrollDirection.Vertical, // Vertical by default
type: MouseWheelScrollType.UnitScroll); // UnitScroll by default
SharpHook provides the IEventSimulator interface, and the default implementation, EventSimulator.
Text Entry Simulation
SharpHook also provides text entry simulation. IEventSimulator contains the SimulateTextEntry method which accepts
a string. The text to simulate doesn't depend on the current keyboard layout. The full range of UTF-16 (including
surrogate pairs, e.g., emojis) is supported.
Note that on Wayland, text entry simulation is not supported.
Low-Level Functionality
SharpHook exposes the functionality of libuiohook through low-level providers in the SharpHook.Providers namespace.
The SharpHook.Data namespace contains types which represent the data used by libuiohook.
In general, you don't need to use the low-level types directly. Instead, use the higher-level interfaces and classes provided by SharpHook. However, you should still read this section to know how the high-level features work under the hood.
There are multiple interfaces in SharpHook.Providers, each of which represents a part of libuiohook's functionality.
SharpHook.Providers.UioHookProvider implements all of these interfaces and simply calls the corresponding functions in
libuiohook. In order to use this class, use UioHookProvider.Instance – its single instance.
IGlobalHookProvider contains the following members for working with the global hook:
SetDispatchProc– sets the function which will be called when an event is raised by libuiohook.Run– creates a keyboard and mouse global hook and runs it on the current thread, blocking it untilStopis called.RunKeyboard– creates a keyboard-only global hook and runs it on the current thread, blocking it untilStopis called.RunMouse– creates a mouse-only global hook and runs it on the current thread, blocking it untilStopis called.Stop– stops the global hook.KeyTypedEnabled- gets or sets the value which specifies whether events of typeKeyTypedare enabled.
You have to remember that only one global hook can exist at a time since calling SetDispatchProc will override the
previously set one. Also, running a global hook when another global hook is already running will corrupt the internal
global state of libuiohook.
IEventSimulationProvider contains the PostEvent method for simulating input events. It also contains the PostText
method which simulates text entry. On Linux, it's required to create virtual input devices before simulating input
events. IEventSimulationProvider contains the InitializeVirtualDevices and DestroyVirtualDevices methods for that.
All higher-level classes accept low-level providers in their constructors. By default, they use UioHookProvider, but
it can be swapped for a fake provider in testing, for example.
Here's the list of all interfaces in SharpHook.Providers:
IAccessibilityProvider– provides configuration for the macOS Accessibility API.IDeviceProcsProvider– provides a way to override privileged device opening/closing functions on Linux.IEventSimulationProvider– provides the event simulation functionality.IFeatureProvider– provides information on optional features supported by the current platform.IGlobalHookProvider– provides the global hook functionality.IKeyboardInfoProvider– provides low-level information about the keyboard.ILinuxBackendProvider– provides the Linux backend configuration.ILoggingProvider– provides the libuiohook logging functionality.IMouseInfoProvider– provides low-level information about the mouse.IScreenInfoProvider– provides low-level information about screens.
Querying Optional Feature Support
Some libuiohook features are considered 'optional' and are not supported on all platforms. The IFeatureProvider
interface has the GetOptionalFeatureSupport method which returns UioHookFeature – a flag enum which represents the
optional features and has the following values:
EventSuppression– if this feature is supported, then event suppression works.KeyTypedEvents– if this feature is supported, then events of typeKeyTypedwork. If not, then callingUioHookProvider.Instance.KeyTypedEnabled = truedoes nothing.PostText– if this feature is supported, then simulating text entry works.KeyAutoRepeat– if this feature is supported, then keeping a key pressed will raise repeatedKeyPressedevents. If not, the only oneKeyPressedevent will be raised.AbsoluteMouseMovement– if this feature is supported, then mouse motion events will always include absolute mouse coordinates, soMouseMovedorMouseDraggedwill always be raised. If not, thenMouseMovedRelativeorMouseDraggedRelativemay be raised instead.AbsoluteMouseButtonCoordinates– if this feature is supported, then mouse coordinates will be present inMousePressed,MouseReleased,MouseClicked, andMouseWheelevents. If not, then the coordinates will always be (0, 0).PointerProperties– if this feature is supported, then theGetPointerAccelerationMultiplier,GetPointerAccelerationThreshold, andGetPointerSensitivitymethods inIMouseInfoProviderwork. If not, then they always return-1.
Windows and macOS support all of these features. X11 supports all of them, except EventSuppression. Wayland supports
none of these features.
Logging
libuiohook can log messages throughout its execution. By default the messages are not logged anywhere, but you can get
these logs by using the ILogSource interface and its default implementation, LogSource:
using SharpHook.Logging;
var logSource = LogSource.RegisterOrGet(minLevel: LogLevel.Info);
logSource.MessageLogged += this.OnMessageLogged;
private void OnMessageLogged(object? sender, LogEventArgs e) =>
this.logger.Log(this.AdaptLogLevel(e.LogEntry.Level), e.LogEntry.FullText);
ILogSource extends IDisposable – you can dispose of a log source to stop receiving libuiohook messages.
An EmptyLogSource class is also available – this class doesn't listen to the libuiohook logs and can be used instead
of LogSource in release builds.
Testing
You can use the SharpHook.Testing package to simplify testing as it provides test utility classes.
Icon
Icon made by Freepik from www.flaticon.com.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-maccatalyst26.0 is compatible. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net10.0-maccatalyst26.0
- No dependencies.
NuGet packages (18)
Showing the top 5 NuGet packages that depend on SharpHook:
| Package | Downloads |
|---|---|
|
GetIt
.NET library to help introduce programming in a funnier way. Inspired by Scratch and Turtle graphics. |
|
|
SharpHook.Reactive
SharpHook provides a cross-platform global keyboard and mouse hook, event simulation, and text entry simulation for .NET. |
|
|
VL.IO.MouseKeyGlobal
Global mouse and keyboard hook for vvvv gamma based on Sharphook by Tolik Pylypchuk |
|
|
Agibuild.Fulora.Avalonia
Cross-platform WebView control for Avalonia UI with native platform adapters (WKWebView on macOS/iOS, WebView2 on Windows, WebKitGTK on Linux, Android WebView). Provides embedded WebView, popup dialog, and OAuth authentication flows. |
|
|
CrossSharp.Application
Cross-platform UI c# library supporting Linux, Windows and MacOs |
GitHub repositories (24)
Showing the top 20 popular GitHub repositories that depend on SharpHook:
| Repository | Stars |
|---|---|
|
timschneeb/GalaxyBudsClient
Unofficial Galaxy Buds Manager for Windows, macOS, Linux, and Android
|
|
|
Jeric-X/SyncClipboard
跨平台剪贴板同步、历史记录管理工具 / Cross-platform cipboard syncing, history management tool
|
|
|
SciSharp/BotSharp
AI Multi-Agent Framework in .NET
|
|
|
CXWorld/CapFrameX
Frametime capture and analysis tool
|
|
|
flyingpie/windows-terminal-quake
Enable Quake-style dropdown for (almost) any application.
|
|
|
ETS2LA/ETS2LA
Plugin based interface program for ETS2/ATS.
|
|
|
Sidekick-Poe/Sidekick
The main repository for the Sidekick project, a companion trade tool for Path of Exile and Path of Exile 2.
|
|
|
verybadcat/CSharpMath
LaTeX. in C#. (ported from the wonderful iosMath project).
|
|
|
awaescher/StageManager
🖥️ Stage Manager for Microsoft Windows (feasibility study)
|
|
|
ShareX/XerahS
XerahS is a cross platform reimagining of the ShareX user interface built with Avalonia. It targets modern UX modular architecture and long term maintainability while preserving core workflows speed and reliability. It provides a foundation for future desktop experiences on Windows, macOS, and Linux with consistent accessible design.
|
|
|
MaaXYZ/MFAAvalonia
基于 Avalonia 的 MAAFramework 通用 GUI 项目 | A universal GUI project for MAAFramework based on Avalonia
|
|
|
lulzsun/RePlays
Open-source game recording management software
|
|
|
Particle1904/DatasetHelpers
Dataset Helper program to automatically select, re scale and tag Datasets (composed of image and text) for Machine Learning training.
|
|
|
tghamm/Anthropic.SDK
An unofficial C#/.NET SDK for accessing the Anthropic Claude API. This package is not affiliated with, endorsed by, or sponsored by Anthropic. Anthropic and Claude are trademarks of Anthropic, PBC.
|
|
|
PizzaLovers007/AdofaiTweaks
Helpful tweaks for A Dance of Fire and Ice
|
|
|
AvionBlock/VoiceCraft
VoiceCraft software to implement proximity VC for Minecraft Bedrock Edition (THIS IS A MIRROR OF THE GITLAB REPO!)
|
|
|
dan0v/AmplitudeSoundboard
A sleek, cross-platform soundboard, available for Windows, MacOS, and Linux
|
|
|
jooapa/jammer
light-weight CLI music player with Soundcloud, Youtube, Rss, Midi Support for Win, Linux & OSX
|
|
|
AlizerUncaged/waifu-desktop
🎂 your waifu, right on your desktop!
|
|
|
pedro-quiterio/PoeAncientsPriceHelper
A screen overlay for Path of Exile 2 that reads your currency-exchange list and shows live poe.ninja prices right next to each item.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 8.0.0 | 728 | 8/24/2026 |
| 7.1.3 | 12,308 | 7/8/2026 |
| 7.1.2 | 7,368 | 5/25/2026 |
| 7.1.1 | 48,528 | 12/30/2025 |
| 7.1.0 | 22,659 | 11/16/2025 |
| 7.0.3 | 7,462 | 10/5/2025 |
| 7.0.2 | 3,091 | 9/21/2025 |
| 7.0.1 | 11,152 | 8/17/2025 |
| 7.0.0 | 2,331 | 8/10/2025 |
| 6.2.0 | 2,430 | 7/19/2025 |
| 6.1.2 | 3,507 | 6/22/2025 |
| 6.1.1 | 2,002 | 6/3/2025 |
| 6.1.0 | 1,199 | 5/23/2025 |
| 6.0.0 | 1,470 | 5/18/2025 |
| 5.3.9 | 25,704 | 3/29/2025 |
| 5.3.8 | 36,044 | 9/27/2024 |
| 5.3.7 | 17,787 | 7/9/2024 |
| 5.3.6 | 4,154 | 5/22/2024 |
| 5.3.5 | 6,872 | 5/20/2024 |
| 5.3.4 | 1,315 | 5/5/2024 |