Click here to Skip to main content
Click here to Skip to main content

Processing Global Mouse and Keyboard Hooks in C#

By , 31 Aug 2011
 

NEWS

This article was posted in 2004 and updated in 2006 and 2008. During all this time until now I receive a lot of positive feedback and recommendations. There where also many useful contributions which where usually posted as code snippets in forum. Now instead of publishing yet another version on my own I decided to ask you all to actively participate. So please be enthusiastic, feel free to join the project at globalmousekeyhook.codeplex.com

You can help by:
  • Contributing code.
  • Creating issue items requesting additional features or reporting defects.
  • Voting for features and fixes you are interested in.
  • Testing the component in different environments.
  • Writing developer documentation.

This will us also allow to keep this original article up to date.

Thank you all for all your great comments on CodeProject forum and looking forward for your brilliant contributions at globalmousekeyhook.codeplex.com

Introduction

This class allows you to tap keyboard and mouse and/or to detect their activity even when an application runs in the background or does not have any user interface at all. This class raises common .NET events with KeyEventArgs and MouseEventArgs, so you can easily retrieve any information you need.

Background

There are a number of applications that run in the background and detect user inactivity to change their mode. For example, MSN Messenger (or any other messenger). I was going to write such an application, so I searched MSDN and found "exactly" what I needed: 318804 - HOW TO: Set a Windows Hook in Visual C# .NET. This article describes how to tap the mouse movement, but it works only when an application is active. At the end of this article, I found this explanation: "Global hook is not supported in .NET Framework. You cannot implement global hooks in Microsoft .NET Framework...". Anyway, I continued my research and found out that there are exceptions. There are WH_KEYBOARD_LL and WH_MOUSE_LL hooks that can be installed globally. So, I have basically replaced WH_MOUSE with WH_MOUSE_LL in the MSDN example, and it works.

The second step was to extract the information received into a .NET EventArgs and raise the appropriate events.

I found a similar article in CodeProject, under Global System Hooks in .NET by Michael Kennedy, but what I dislike is, there is an unmanaged DLL in C++ that is a main part of this solution. This unmanaged DLL is in C++, and a number of classes make it complicated to integrate it in my own tiny application.

Revisions

This article was posted in 2004 and updated in 2006. During all this time until now I receive a lot of positive feedback and recommendations. There were also a number of technology improvements like .NET Framework 3.5 or Visual Studio 2008. So I have decided to update it once more.

I have refactored and improved the solution, made it more flexible, stable and efficient. But this refactoring also had some drawbacks:

  1. Number of code lines and files has grown.
  2. Backward compatibility to older .NETs is lost.

That's why I attend to leave the old version also to be available for download.

Using the Code [Version 2]

The Simple Way

If you are developing a Windows Forms application and prefer drag & drop programming, there is a component named GlobalEventProvider inside the assembly Gma.UserActivityMonitor.dll. Just drag and drop it to your form and create events using the property editor events tab.

The Alternative Way

Use events provided by the static class HookManager. Note that the sender object in events is always null.

For more usage hints, see the source code of the attached demo application.

Using the Code [Version 1]

To use this class in your application, you need to just create an instance of it and hang on events you would like to process. Hooks are automatically installed when the object is created, but you can stop and start listening using appropriate public methods.

UserActivityHook actHook;
void MainFormLoad(object sender, System.EventArgs e)
{
    actHook= new UserActivityHook(); // crate an instance

    // hang on events

    actHook.OnMouseActivity+=new MouseEventHandler(MouseMoved);
    actHook.KeyDown+=new KeyEventHandler(MyKeyDown);
    actHook.KeyPress+=new KeyPressEventHandler(MyKeyPress);
    actHook.KeyUp+=new KeyEventHandler(MyKeyUp);
}

Now, an example of how to process an event:

public void MouseMoved(object sender, MouseEventArgs e)
{
    labelMousePosition.Text=String.Format("x={0}  y={1}", e.X, e.Y);
    if (e.Clicks>0) LogWrite("MouseButton     - " + e.Button.ToString());
}

Changes and Updates from [Version 0] to [Version 1]

I'd like to thank you all for all the useful comments in the discussion forum. There were a lot of bugs and proposals posted after this article was published on 4th June, 2004. Over and over again came the same topics, and I had to refer to previous posts in the discussion, that is why I have decided to revise the code and publish a FAQ. Here is the list of the most important changes:

  • The project was converted into Visual Studio 2005
  • The problem with upper case characters is solved
  • Mouse wheel information is now included in event arguments
  • Better exception handling
  • Cancellation of keyboard events using the Handled property of event arguments
  • XML documentation of functions

FAQ [Version 1]

Question

The project cannot be run in Visual Studio .NET 2005 in debug mode because of an exception error caused by calling the SetWindowsHookEx. Why? Is it a problem of .NET 2.0?

Answer

The compiled release version works well so that cannot be a .NET 2.0 problem. To workaround, you just need to uncheck the check box in the project properties that says: "Enable Visual Studio hosting process". In the menu: Project -> Project Properties... -> Debug -> Enable the Visual Studio hosting process.

Question

I need to suppress some keystrokes after I have processed them.

Answer

Just set the e.Handled property to true in the key events you have processed. It prevents the keystrokes being processed by other applications.

Question:

Is it possible to convert your global hooks to application hooks which capture keystrokes and mouse movements only within the application?

Answer

Yes. Just use...

private const int WH_MOUSE = 7;
private const int WH_KEYBOARD = 2;

... everywhere, instead of:

private const int WH_MOUSE_LL = 14;
private const int WH_KEYBOARD_LL = 13;

Question

Does it work on Win98 (Windows ME, Windows 95)?

Answer

Yes and No. The global hooks WH_MOUSE_LL and WH_KEYBOARD_LL can be monitored only under Windows NT/2000/XP. In other cases, you can only use application hooks (WH_MOUSE and WH_KEYBOARD) which capture keystrokes and mouse movement only within the application.

Question

I have a long delay when closing applications using hooks by clicking the x button in the titlebar. If I close the application via another event (button click) for example, that works fine.

Answer

It's a known bug of Microsoft. It has to do with the Windows themes. If you disable the Windows themes, the problem goes away. Another choice is to have the hook code run in a secondary thread.

Question

How do I catch key combinations like Ctrl+Shift+A?

Answer

You'll have to track which keys have gone down but not up. Only the most recently pressed key keeps sending KeyDown messages, but the others will still send a KeyUp when released. So if you make three flags IsCtrlDown, IsShiftDown, and IsADown, and set them to true at KeyDown and false at KeyUp, the expression (IsCtrlDown && IsShiftDown && IsADown) will give you the required result.

Question

Does it works with .NET Framework 1.1 and Visual Studio 2003?

Answer

Yes. The file UserActivityHook.cs can be used without any changes, in a Visual Studio 2003 .NET 1.1 project.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

George Mamaladze
Software Developer
Germany Germany
Tweeter: @gmamaladze
Google+: gmamaladze
Blog: gmamaladze.wordpress.com
Follow on   Twitter

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerHow do I catch key combinations like Ctrl+Shift+A? PinmembergNapoleonis6-Jun-13 7:58 
Is pretty simple.
 
private void HookManager_KeyDown(object sender, KeyEventArgs e)
        {
            textBoxLog.AppendText(string.Format("KeyDown - {0}\n", e.KeyCode));
            textBoxLog.ScrollToCaret();
 
            if (IsCtrlDown() && IsShiftDown() && e.KeyCode == Keys.A)
            {
                MessageBox.Show("Ctrl+Shift+A is pressed !!");
            }
 
        }
 
        bool IsCtrlDown()
        {
            if ((ModifierKeys & Keys.Control) == Keys.Control)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
 
        bool IsShiftDown()
        {
            if ((ModifierKeys & Keys.Shift) == Keys.Shift)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

QuestionHandling events in a Remote Desktop Session PinmemberJeeeJay14-May-13 12:57 
My app saves a screenshot after the mouse-down event. Say I'm installing a software and the app is running. A screen shot is saved every time I click 'Next' on the wizard. However; if I connect to a different machine via Remote Desktop and perform the same steps with the app running, no images are captured and saved (on that machine). Any idea what could be the reason behind it?
QuestionDoes it need any independent Thread to work? PinmemberSoroosh Mortezapoor10-May-13 11:35 
Hi
 
I am going to embed your magnificent code into a simple Console Application. I'm wondering if I have to change any thing in the code's structure to make this code work in an independent thread so locking main thread won't cause this module to stop hooking.
here is the simple main method which doesn't work
static void Main(string[] args)
{
    HookManager.KeyPress += HookManager_KeyPress;
    Console.WriteLine("DONE");
    Console.Read();
}
 
static void HookManager_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    throw new NotImplementedException();
}

GeneralMy vote of 5 PinmemberMember 999405817-Apr-13 1:55 
excelent; but because of win32error ; I used version3 and is well done;
http://globalmousekeyhook.codeplex.com/
Questionin my game it is not working ! PinmemberPhoenix-300031-Mar-13 21:50 
I found your demo : GlobalHookDemo from. It is (almost) exactly What I searched, but...This application stop to show the keys pressed when I click on the windows of my game Blush | :O .
 
But (again) if I click in my browser or another windows application. This GlovalHookDemo.exe work very well. So only When I want to use with my game, this application stop to work.
 
REMARK : My game (online) is Savage for Windows (I have Windows 8) that can be installed for free from www.newerth.com. This problem appears in both in Full screen mode or in window screen.
 
For me, this is an amazing story that is beyond me, I'm sorry. Why is my game so specific? is it was not "buildé" in a Windows environment (I actually think it was compiled in a LINUX environment ... is it because of this problem that library functions used by GlobalHookDemo SetWindowsHookEx does not work?).

Fundamental issue that calls into question the usefulness of my life on my planet. We are so little without Windows.?? Cry |: (( (google translater was used sorry)
 
===================================
 
Bonjour, merci Smile | :) !
 
J'ai trouvé une démo: GlobalHookDemo sur notre site. Il est (presque) exactement ce que je recherche, mais ... Cette application arrête de montrer les touches pressées, lorsque je clique sur la fenêtre de mon jeu Blush | :O . et bien sur en cours de partie. En contrepartie, cette application marche très bien, dans toutes autres situations (Navigation dans les browsers, notepad, openoffice, etc.)
 
Mon jeu (en ligne) est Savage pour Windows que l'on peut installer gratuitement à partir de www.newerth.com). ce problème apparait aussi bien en Plein écran que dans une fenêtre Windows.
 
Pour moi, c'est une histoire incroyable qui me dépasse, j'en suis désolé. Pourquoi mon jeu est-il si spécifique ? est-ce qu'il n'a pas été "buildé" dans un environnement Windows (je pense en fait qu'il a été compilé dans un environnement LINUX... est-ce à cause de ce problème que les fonctions de la bibliothèque SetWindowsHookEx utilisé par GlobalHookDemo, ne fonctionne pas ?).
 
Question fondamentale qui remet en question l'utilité de mon existence sur ma planète. Sommes nous si peu de chose sans Windows .??? Cry | :((
 
Pardon pour mon Français Smile | :) .
QuestionNot working on ie7 windows xp Pinmemberparag_117-Mar-13 21:56 
I have included the dll of the given project to one of my windows application.
It works properly in windows 7(ie8,ie9) but events(mouse click,keypress etc.) are not getting fired in windows xp having ie7,ie8 installed....?
 

Any clue what i am missing here.
Buge.Control, e.Shift, e.Alt in KeyUp and KeyDown don't seem to work PinmemberLogslava8-Mar-13 9:08 
Hi,
 
I am having a problem determining if the Control key is pressed in the KeyDown event. The e.Control always returns false. The same problem with Shift and Alt and the KeyUp event.
 
Can you please check if it works for you or is it a bug?
 
Regards
GeneralMy vote of 5 Pinmembersadmonew6-Mar-13 13:09 
بسیار عالی
very very nice
GeneralMy vote of 5 PinmemberAsad Naeem25-Feb-13 20:39 
Simply the best
QuestionI am getting Win32Exception was unhandled [modified] PinmemberMember 770255323-Feb-13 9:19 
Hello I am using c# express 2010 and getting this exception:
Win32Exception was unhandled: The specified module could not be found.
How can i solve it?
 
I just have this:
UserActivityHook actHook = new UserActivityHook();
actHook.OnMouseActivity += new MouseEventHandler(MouseMoved);

modified 23-Feb-13 15:27pm.

AnswerRe: I am getting Win32Exception was unhandled PinmemberMember 841830111-Mar-13 1:59 
QuestionCannot get this to run despite "using gma.XXXX;" and having the DLL referenced PinmemberMember 976603518-Jan-13 14:47 
Im new to C# and have been looking for like over 12hrs to find a beginner-friendly solution to my needs. This seem to be my only chance for getting with my project.
 
I think my main problem is, that compared to the Demo project, I do not get " this.globalEventProvider1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.HookManager_KeyUp);" in my FormDesigner when using the Property Events of my Form. Only the Default "Form1" Events.
 
I tried dragging the GlobalEventHandler from the Objectcatalog onto my "Form" in any thinkable way... but it does not work. How am I supposed to do or drag this onto my Form exactly? No matter where I drag it, keep getting the black "cross" symbol.
 
"If you are developing a Windows Forms application and prefer drag & drop programming, there is a component named GlobalEventProvider inside the assembly Gma.UserActivityMonitor.dll. Just drag and drop it to your form and create events using the property editor events tab."
 
Some Step by Step help or suggestions would really be welcome. If you need more information, ask away. Windows 7 Ultimate 64 Bit. Project most probably 64 Bit too.. Visual Studio Express 2010.
 
Thanks in advance.
AnswerRe: Cannot get this to run despite "using gma.XXXX;" and having the DLL referenced PinmemberMember 976603519-Jan-13 1:59 
GeneralMy vote of 5 PinmemberMidnight Ahri16-Jan-13 16:17 
Thank you Sir, I love your code. <3
QuestionVote of 5 PinmemberKalpana Volety11-Jan-13 9:25 
My vote of 5.
Worked on windows 7 as well.
 
Thank you,
Kalpana Volety
PDF Tools
QuestionWhich Application was mouse clicked PinmemberMember 768986128-Dec-12 22:38 
Hi George,
 
Thank you for making this code public.
 
Just one question please. It is possible to capture the application name which was clicked by the mouse ?
 
Any help appreciated, as I am still a beginner . .
 
ninu
ninu

GeneralMy vote of 5 PinmemberReynaldots28-Nov-12 18:59 
Thanks!!!
QuestionMouse disable from system PinmemberNeelmaniN28-Nov-12 2:52 
sir,
is it possible to disable mouse from system if yes then how? Please help.
thanks Sigh | :sigh:
GeneralMy vote of 5 PinmemberMember 95864219-Nov-12 10:51 
Works like a charm!
QuestionThe specified module could not be found Pinmemberjeff gonzales26-Oct-12 8:30 
Hi,
 
I created a basic windows form app in Visual Studio 2010 but am having problems.
 
Basically I dragged the Gma object onto the form and added an event for mouse clicks.   When I start the app, however, an exception is throw in EnsureSubscribedToGlobalMouseEvents() with the following:
 
The specified module could not be found
 
I turned off Visual Studio hosting for debug but I still get this problem.   Am I missing something?   Please help.
 
Thanks,
gb
AnswerRe: The specified module could not be found Pinmemberluka826-Nov-12 23:53 
AnswerRe: The specified module could not be found PinmemberPedro Lacerda21-Mar-13 9:30 
GeneralRe: The specified module could not be found Pinmembergalaxyyao14-Apr-13 20:22 
QuestionDoesn't work when running a game PinmemberMember 952393217-Oct-12 23:13 
I want to capture keyboard press rate and mouse movement speed while they're playing Slender Man's Shadow http://www.slendermansshadow.com/[^]
 
I modified the demo application [version2] and it work perfectly fine whatever activity I do except while I run the game.
 
What could be the problem? Anyone has some suggestion how to deal with this?
 
Thank you
Questionreally nice Pinmemberseanmchughinfo17-Oct-12 16:58 
thank you. i forgot how nice this was until i lost it.
QuestionConvert to application hook PinmemberKKSharma4-Oct-12 1:27 
Great post George.
 
It warking great for global hooks but I want to convert your global hook to application hook so that it should listen to mouse down event from my application only. I have tried to change in the code as you've suggested, re-built and used the dll in my application but its listening the mouse down event only just once.
 
private const int WH_MOUSE = 7;
 
//install hook
s_MouseHookHandle = SetWindowsHookEx(
    WH_MOUSE,
    s_MouseDelegate,
    Marshal.GetHINSTANCE(
        Assembly.GetExecutingAssembly().GetModules()[0]),
    0);
 
Can you suggest what is going wrong?
 
Thanks in advance,
KKS
SuggestionRe: Convert to application hook PinmemberZemaits11-Nov-12 9:22 
QuestionRe: Convert to application hook Pinmembermaomea7822-Apr-13 23:52 
QuestionHow suppress Ctrl+Alt+Delete ? Pinmemberalao3-Oct-12 0:12 
Hi George,
 
This is excellent, this is exactly what I want.
In fact, I want to not allow a user to access Windows from my application, I successfully to suppress Windows key and Alt+F4. And to suppress the keys combination Ctrl+Alt+Delete, I make two flags IsCtrlDown and IsAltDown and I set them to true at KeyDown and to false at KeyUp, and then i make the below code at KeyDown :
 
if (IsCtrlDown && IsAltDown && e.KeyCode == Keys.Delete) e.Handled = true;
 
But it don't work. Please can you help me, thanks in advance.
AnswerRe: How suppress Ctrl+Alt+Delete ? Pinmembergeekbond11-Oct-12 22:53 
AnswerRe: How suppress Ctrl+Alt+Delete ? Pinmembergsw08-Dec-12 2:17 
GeneralMy vote of 5 Pinmemberlello-323-Aug-12 17:09 
Just fantastic code and extremely useful. Thanks!
QuestionProblem when targeting .NET 4.0 Client Profile PinmemberRoy Ben-Shabat14-Aug-12 11:57 
I discovered some kind of a problem when targeting the project to .net 4.0
i will be happy if you could help me to resolve the issue.. thank you.
Amazing project by the way..
QuestionError 1 PinmemberErrr7179-Aug-12 10:11 
Hi George,
 
I get the following error on "UserActivityHook actHook;"
 
Error 1 The type or namespace name 'UserActivityHook' could not be found (are you missing a using directive or an assembly reference?)
 
I'm using VS 2010, and the target framework is set to 2.0 (same problem with client 4.0)
 
Any ideas what I'm doing wrong?
 
Regards,
Ed
Questionsaving in a file for later use PinmemberMohsinTariq16-Jun-12 9:54 
How can i save the Macro in a file for later use
 
please give me code
QuestionUnhandled Exception Pinmemberjdnd14-Jun-12 2:30 
when running this code, or the demo exe, I receive an unhandled exception
 
The operation Completed Successfully.
 
from the following method
 
private static void EnsureSubscribedToGlobalMouseEvents()
 
I have used this code a few years back with no problems and it was very useful but I have hit a brick wall with this error.
 
any help would be appreciated
        Jay Dee ( www.jdnd.co.uk )

SuggestionRe: Unhandled Exception PinmemberSerge Wenger Work14-Jun-12 20:55 
QuestionNot working WInXP Pinmemberanandkiyer3-Jun-12 13:48 
It works great in Windows 7, but not in WinXP. No errors, no exceptions, but it just doesn't produce any output. .NET framework is available in the machine.
 
ANy ideas?
Cheers,
Anand

Questioni can not found Gma.UserActivityMonitor.dll Pinmemberseoshen27-Apr-12 21:34 
hi i can not found component.please help me.
AnswerRe: i can not found Gma.UserActivityMonitor.dll Pinmemberkali_443-Sep-12 22:15 
GeneralIts awesome !! Pinmemberrasheed.it10-Apr-12 9:44 
Thank you very much .. it is really useful for me. I have implemented keyboard hook and while searching for mouse hook i came across your code. it saves lot of time . thank you   once again.
 
Cheers,
Rashid
Generalreally useful Pinmemberurrry6-Apr-12 10:20 
thanks a lot for the article
really useful
QuestionHook and keypad Pinmemberdelirium66620-Mar-12 0:19 
Hello,
 
I'm doing a Hook program to replace the keypad value by the numbers without activated the numlock. But I'have a problem with the arrows keys, how can i diffrencies the arrows key code between a keypad and the keyboard ?
 
And why this code don't work if((wparam == WM_KEYUP) but this yes : if (!(wparam & 0x70000000))
 
Thanks or your help.
AnswerRe: Hook and keypad Pinmembergeekbond18-Oct-12 3:14 
QuestionHookManager and Windows services Pinmemberbabe5913-Mar-12 22:58 
Hello,
is ti possible to use HookManager in a windows service. I try to do it but event not fire...
Thks
DT
QuestionRe: HookManager and Windows services Pinmembergeekbond18-Oct-12 3:05 
AnswerRe: HookManager and Windows services PinmemberDavid Brunelle24-Oct-12 7:31 
AnswerRe: HookManager and Windows services PinmemberSerge Wenger Work28-Oct-12 23:16 
QuestionEnter Key hook indentify & do an event Pinmemberdharamveersindhi9-Mar-12 22:36 
hi i am using activity hooks. but when i do log write to a text file using append text it's working fine but when pressing enter key it's not doing any thing .
 
i have to make an event like the text box value can insert in grid view or it should go in any kind of file with datetime ?????????
 
how can i do it.
 
after a long RND i did'nt find any thing.
 
please help me ASAP.
QuestionEnter Key hook loag & do an event Pinmemberdharamveersindhi9-Mar-12 22:34 
hi i am using activity hooks. but when i do log write to a text file using append text it's working fine but when pressing enter key it's not doing any thing .
 
i have to make an event like the text box value can insert in grid view or it should go in any kind of file with datetime ?????????
 
how can i do it.
 
after a long RND i did'nt find any thing.
 
please help me ASAP.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130617.1 | Last Updated 31 Aug 2011
Article Copyright 2004 by George Mamaladze
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid