SharpHook 4.0.0

.NET 6.0 .NET Standard 2.0 .NET Framework 4.6.1
dotnet add package SharpHook --version 4.0.0
NuGet\Install-Package SharpHook -Version 4.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SharpHook" Version="4.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SharpHook --version 4.0.0
#r "nuget: SharpHook, 4.0.0"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install SharpHook as a Cake Addin
#addin nuget:?package=SharpHook&version=4.0.0

// Install SharpHook as a Cake Tool
#tool nuget:?package=SharpHook&version=4.0.0


SharpHook provides a cross-platform global keyboard and mouse hook for .NET, and the ability to simulate input events. It is a thin wrapper of libuiohook and provides direct access to its features as well as higher-level types to work with it.


Native Functions of libuiohook

SharpHook exposes the functions of libuiohook in the SharpHook.Native.UioHook class. The SharpHook.Native namespace also contains structs and enums which represent the data returned by libuiohook.

Note: In general, you shouldn't use native methods directly. Instead, use the higher-level types provided by SharpHook.

UioHook contains the following methods for working with the global hook:

  • SetDispatchProc - sets the function which will be called when an event is raised by libuiohook.
  • Run - creates a global hook and runs it on the current thread, blocking it until Stop is called.
  • Stop - destroys the global hook.

Additionally, UioHook contains the PostEvent method for simulating input events, and the SetLoggerProc method for setting the log callback.

libuiohook also provides functions to get various system properties. The corresponding methods are also present in UioHook.

Default Global Hooks

SharpHook provides the IGlobalHook interface along with two 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 TaskPoolGlobalHook();

hook.HookEnabled += OnHookEnabled;
hook.HookDisabled += OnHookDisabled;

hook.KeyTyped += OnKeyTyped;
hook.KeyPressed += OnKeyPressed;
hook.KeyReleased += OnKeyReleased;

hook.MouseClicked += OnMouseClicked;
hook.MousePressed += OnMousePressed;
hook.MouseReleased += OnMouseReleased;
hook.MouseMoved += OnMouseMoved;
hook.MouseDragged += OnMouseDragged;

hook.MouseWheel += OnMouseWheel;

// 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 destroyed. You can subscribe to events after the hook is started.

IGlobalHook extends IDisposable. When you call the Dispose method on a hook, it's destroyed. The contract of the interface is that once a hook has been destroyed, it cannot be started again - you'll have to create a new instance.

Important: Always use one instance of IGlobalHook at a time in the entire application since they all must use the same static method to set the hook callback for libuiohook, and there may only be one callback at a time.

SharpHook provides two implementations of IGlobalHook:

  • SimpleGlobalHook runs all of its event handlers on the same thread where 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.

  • TaskPoolGlobalHook runs 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 handlers. This means that the hook will be able to process all events. This implementation should be preferred to SimpleGlobalHook except for very simple use-cases. But it has a downside - suppressing event propagation will be ignored since event handlers are run on other threads.

The library also provides the GlobalHookBase class which you can extend to create your own implementation of the global hook. It calls appropriate event handlers, and you only need to implement a strategy for dispatching the events.

Reactive Global Hooks

Use the SharpHook.Reactive package for reactive global hooks.

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.Native;

// ...

var simulator = new EventSimulator();

// Press Ctrl+C

// Release Ctrl+C

// Press the left mouse button

// Release the left mouse button

// Move the mouse pointer to the (0, 0) point
simulator.SimulateMouseMovement(0, 0);

// Move the mouse pointer to the (0, 0) point, and scroll the mouse wheel
simulator.SimulateMouseWheel(0, 0, 10, -1);

SharpHook provides the IEventSimulator interface, and the default implementation, EventSimulator, which calls UioHook.PostEvent to simulate the events.


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.Register();
logSource.MessageLogged += this.OnMessageLogged;

private void OnMessageLogged(object? sender, LogEventArgs e) =>
    this.logger.Log(this.AdaptLogLevel(e.LogEntry.Level), e.LogEntry.FullText);

As with global hooks, you should use only one LogSource object at a time. ILogSource extends IDisposable - you can dispose of a log source to stop receiving libuiohook messages. You should keep a reference to an instance of LogSource since it will stop receiving messages when garbage collector deletes it, to avoid memory leaks.


Icon made by Freepik from

Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48 net481
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.6.1

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on SharpHook:

Package Downloads

Provides a cross-platform global keyboard and mouse hook for .NET, and the ability to simulate input events


Global mouse and keyboard hook for vvvv gamma based on Sharphook by Tolik Pylypchuk

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
4.0.0 1,037 11/9/2022
3.1.3 483 10/27/2022
3.1.2 592 10/19/2022
3.1.1 1,668 8/5/2022
3.1.0 660 7/30/2022
3.0.2 2,401 7/1/2022
3.0.1 406 6/25/2022
3.0.0 787 3/27/2022
2.0.0 685 2/4/2022
1.1.0 838 12/4/2021
1.0.1 626 11/21/2021
1.0.0 401 11/8/2021
1.0.0-preview.4 106 11/6/2021
1.0.0-preview.3 121 11/1/2021
1.0.0-preview.2 107 10/26/2021
1.0.0-preview.1 100 10/26/2021