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

Global Windows Hooks

By , 24 Sep 2010
 

Introduction

The WindowsHookLib is a single library to hook the mouse, keyboard and the clipboard system wide. WindowsHookLib library has been rewritten in C# and therefore it uses Common Language Runtime (CLR). This means that the library can be referenced from various projects in .NET. The mouse and keyboard hooks are low level so you can use the Handled property of the MouseEventArgs or the KeyboardEventArgs to prevent the windows messages being passed to the other applications. Note you need to use the DLL file, not the classes in your projects; otherwise they might not work correctly.

  • Clipboard hook
  • Keyboard hook
  • Mouse hook

This component differs from what I have seen in other similar articles, by providing two more things:

  1. Preventing a message to be passed to other windows
  2. Raising the MouseClick and MouseDoubleClick events (I have never seen implementation of this in other low level hooks!)

Mouse Hook

The MouseHook class of the 'WindowsHookLib' library is designed to hook the mouse globally and raise some useful events. Since this hook is low level and low level mouse hooks don't get the MouseClick and MouseDoubleClick messages, it simulates these events. In order to use these events, the class object variable should be declared with the WithEvents keyword.

The MouseDown, MouseUp, MouseWheel, and MouseMove event handlers have a WindowsHookLib.MouseEventArgs class object which provides all the relevant information about the mouse as does the System.Windows.Forms.MouseEventArgs, and two additional properties, Handled and Control. You can set the Handled property to True to prevent the message from being passed to the other windows. The Control property provides the handle of the control under the mouse pointer. If you decide to set the Handled property in the MouseUp event, then it is recommended to set it in the MouseDown event as well for application performance. Conversely, if you decide to set the Handled property in the MouseDown event, then it is recommended to set it in the MouseUp event.

Note: If you set the Handled property in the mentioned events unconditionally, then you might not be able to use the mouse. To condition (block the mouse message to be passed to other windows or controls), you should compare the Control property's value against allowed control handle(s). If the allowed controls' handle list doesn't contain the Control property value, then you can set the Handled property to True; otherwise, don't set it. You can check the demo project's examples to see how you can condition the mouse handled process.

Note: Before you exit your application, you must call the hook object's Dispose method to uninstall the hook and free the class variables.

Keyboard Hook

The KeyboardHook class of the 'WindowsHookLib' library can be used to hook the keyboard globally. The class provides three events whose KeyDown and KeyUp event handlers contain a WindowsHookLib.KeyEventArgs object that has all the relevant information about the key as the System.Windows.Forms.KeyEventArgs. As with the mouse hook, you can set the Handled property to True in the KeyDown and KeyUp event handlers to prevent the message from being passed to other windows.

Clipboard Hook

The ClipboardHook class of the 'WindowsHookLib' library can be used to hook a window to the clipboard chain. The class provides two events, ClipbordChanged and StateChanged. The ClipboardChanged event handler contains a WindowsHookLib.ClipboardEventArgs object that has all the relevant information about the event.

Using the Code

Note: You need to use the DLL file by referencing it in your project, not the classes; otherwise, they might not work correctly. If you need the method descriptions, then you need to copy the 'WindowsHookLib.xml' file into your project folder.

Imports WindowsHookLib

'Class level declarations
Dim WithEvents kHook As New KeyboardHook
Dim WithEvents mHook As New MouseHook
Dim WithEvents cHook As New ClipboardHook

'Allowed control handle list
Dim alowedList As New List(Of IntPtr)

Try
    'Install the hooks
    kHook.InstallHook()
    mHook.InstallHook()
    cHook.InstallHook(Me) 'takes a window as its parameter.
Catch ex As Exception
    Console.WriteLine(ex.Message)
End Try

Try
    'Remove the hooks
    kHook.RemoveHook()
    mHook.RemoveHook()
    cHook.RemoveHook()
Catch ex As Exception
    Console.WriteLine(ex.Message)
End Try

Private Sub kHook_KeyDown( _
  ByVal sender As Object, _
  ByVal e As WindowsHookLib.KeyEventArgs) Handles kHook.KeyDown
    'Block Alt+PrintScreen key combination
    e.Handled = (e.Modifiers = Keys.Alt AndAlso _
                 e.KeyCode = Keys.PrintScreen)
End Sub

Private Sub mHook_MouseDown( _
  ByVal sender As Object, _
  ByVal e As WindowsHookLib.MouseEventArgs) Handles mHook.MouseDown
    'Set the Handled property for the mouse down event
    'to block the mouse down message for the 
    'controls that are not in the alowedList.
    e.Handled = Not Me.alowedList.Contains(Ctype(sender,IntPtr))
    'Do some other things here
    '...
    '...
End Sub

Private Sub mHook_MouseUp( _
  ByVal sender As Object, _
  ByVal e As WindowsHookLib.MouseEventArgs) Handles mHook.MouseUp
    'Set the Handled property for the mouse up event
    'to block the mouse up message for the 
    'controls that are not in the alowedList.
    e.Handled = Not Me.alowedList.Contains(Ctype(sender,IntPtr))
    'Do some other things here
    '...
    '...
End Sub

Private Sub cHook_ClipboardChanged( _
  ByVal sender As Object, _
  ByVal e As WindowsHookLib.ClipboardEventArgs) _
  Handles cHook.ClipboardChanged
    'The clipboard content is changed, do something about it.
    '...
    '...
End Sub

For more examples, check out the source code and demo files.

Background

In the core of this component lies the API methods. All hooks use some API methods to hook and monitor for Windows messages. The following list is the API methods that have been used:

  • SetWindowsHookEx
  • UnhookWindowsHookEx
  • CallNextHookEx
  • WindowFromPoint
  • SendInput
  • SetClipboardViewer
  • ChangeClipboardChain

Points of Interest

I learned many things from this project like how to make a DLL file component that can be used in various projects (VB.NET, C#, C++, J#) in the .NET environment. Also, how to apply attributes to classes or methods that will make a component professional.

Since low level mouse hooks don't get the MouseClick and MouseDoubleClick event messages (which I believe are generated by a window that gets the MouseDown and MouseUp messages), I tried to simulate these events such that they are generated in the same pattern as the Windows MouseClick and MouseDoubleClick events.

WindowsHookLib Information

  • Author: Arman Ghazanchyan
  • Current assembly version: 1.1.1.2
  • Current file version: 1.0.0.6
  • WindowsHookLib webpage

History

  • Updated assembly version 1.1.0.1. This update addresses all hooks.
    • The WindowsHookLib assembly is signed.
    • A clipboard hook is added - New
  • Updated assembly version 1.1.0.2. This update addresses the Keyboard hook.
    • Small change in the KeyEventArgs class
  • Updated assembly version 1.1.0.5. This update addresses to all hooks.
    • Small changes and fixes
  • Updated assembly version 1.1.1.0. This update addresses to all hooks.
    • Some changes and fixes
  • Updated assembly version 1.1.1.2. This update addresses to all hooks, the update is highly recommended.
    • The library is rewritten in C# language.
    • There are many fixes and optimizations to the library.
    • Clipboard Hook bug fix. The hook was not implementing correctly in the previous versions which would lead to breaking up the windows clipboard chain. This version fixes the problem.
    • This version of the library is smaller in size than the previous versions.

License

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

About the Author

VBDT
Software Developer (Senior)
United States United States
No Biography provided

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   
GeneralMy vote of 5memberDwayne J. Baldwin8-Feb-11 14:05 
I really enjoyed this, not only for technical merit, but for demonstrating .net use in multiple languages.
GeneralNot capturing exect Charactermembereg_Anubhava30-Jan-11 21:06 
Hello Sir,
 

I have generate a problem.The Problem is when i am changing my keyboard Language to Russian (From Control Panel - Regional and Language Settings -Keyboard Settings). Then my keyboard shows russian character but Keyboard Hook Capture a US format.
 

Thanks in advanced.
 

Thanks
If you can think then I Can.

GeneralRe: Not capturing exect CharactermemberVBDT31-Jan-11 16:54 
Hi,
 
Well, that is not a problem of the hook. Hook uses and returns Dot Net "Keys" enumeration object in event handler parameter and there are no Russian keys in there. If you want to get the Russian chars, than you need to do the conversion yourself.
 
Regards,
VBDT
GeneralRe: Not capturing exect Charactermembereg_Anubhava4-Feb-11 23:48 
You can capute the Keystrock according to selected Keyboard Layout.
With the use of below function API u can use the unicode with ur Keyhook.
 
MapVirtualKeyEx
ToUnicodeEx
If you can think then I Can.

QuestionIt is not working for mememberMatchlighter15-Dec-10 15:42 
I am running Windows 7 x64 and .NET 4.0. The demo works fine for me, but I am having trouble getting it to working in my own project. I had to convert it to Any CPU in order for it to be compatible with the rest of my project, but it is not reporting anything. I have told it to install the hooks. Do you know what the problem is and how I can fix it?
AnswerRe: It is not working for mememberVBDT16-Dec-10 18:53 
The dll is 32 bit, there for you should have your project set to x86 not Any CPU. x86 will work on 32bit and x64 systems thanks to a layer (WoW64) that Microsoft added to x64 systems so that they can run 32bit applications.
 
http://en.wikipedia.org/wiki/WoW64[^]
GeneralRe: It is not working for mememberMatchlighter17-Dec-10 15:36 
I have done that, but it still does not work
 
Here is my code. Perhaps you could discern the problem?
 
    Dim WithEvents MainMouseHook As New MouseHook()
 
    Private Sub QuickBulletin_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 
        MainMouseHook.InstallHook()
 
        'Other code...

    End Sub
 
    Private Sub MyMouseHook_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MainMouseHook.MouseDown
        Debug.Print("Global Click")
    End Sub
 
 
My Debug panel never prints "Global Click". I have looked at your demo application (which works), but I can't find the difference. Thanks for your assistance Smile | :)
GeneralRe: It is not working for mememberVBDT17-Dec-10 19:32 
Hi,
If you are using the previous version of the hook and framework 4.0 than it will not work. The previous version of the hook works on 3.5 and above. The current assembly version of the dll is 1.1.1.3. Download it by clicking on the "Download latest version" or product website on top of this form.
GeneralRe: It is not working for mememberMatchlighter17-Dec-10 20:03 
I just figured it out. It was not a problem with the library. Somehow, the Define Debug constant got unchecked in my project at one point so it was not printing. Thanks for the help though!
QuestionEvents Stop Firing in Win7memberJon Gross4-Nov-10 4:25 
Hi VBDT,
 
I have been using your component for a while on WinXP and it has worked perfectly. When we started using it on Win7 everything appeared fine but as we tested it harder we stop receiving events from the ‘MouseMove’ event after several minutes. After some additional testing we noticed the same thing with the ‘KeyDown’ event. The mouse and keyboard event do not stop working at the same time and fail in no specific order. Again, everything works perfectly at first and then randomly after a few minutes events stop firing, only on Win7.
 
When we notice the mouse events are no longer firing, I added a button that executes the following 2 lines and everything works for a few more minutes.
gmh = New MouseHook
gmh.InstallHook()
 
When we first noticed the problem we were using the 1.0 version of your component with the .Net 2.0 framework. Now we are using 1.0.0.7 and .Net 3.0 framework and experience the same issues.
 
I am not seeing any exceptions being thrown or anything in the event viewer. Any help would be much appreciated.
 

- Jon
AnswerRe: Events Stop Firing in Win7memberVBDT4-Nov-10 17:49 
Hi Jon,
 
What kind of tests are you performing? I will test it at my work on windows 7 and will post the results in here.
GeneralRe: Events Stop Firing in Win7memberJon Gross5-Nov-10 4:05 
Our testing is pretty simple it is just clicking around in our application but it needs to be done for several minutes.   We have tested on 4 different Win7 computers and experienced the same result on all of the computers.   I am willing to send you the application and detailed instructions if you will send me your email address.   We should keep all of the technical info as part of this thread but some of the private will need to be taken off line.   Please contact me at   jon.gross < at > talario < dot > com
GeneralRe: Events Stop Firing in Win7memberJon Gross5-Nov-10 7:03 
I have a simple test program that is able to reproduce the error.   It appears that when the computer is under load the error appears.   Then when I close the program and release the hook I get an "Invalid hook handle".   Glad to send you the source code if that would help you.
GeneralRe: Events Stop Firing in Win7memberVBDT6-Nov-10 9:49 
Hi,
 
Make sure you have the latest version of the hook. You can get the latest version of the hook by clinking the "Download latest version" link above.
GeneralRe: Events Stop Firing in Win7memberVBDT6-Nov-10 9:42 
Hi Jon,
 
I have tested the hook demo on windows 7 at my work for hours and have not seen the problem you are describing. Try the hook demo project and see if you encounter the problem. The problem could be system related since my tests do not show any problem whit the library.
You can download the demo project from my website http://www.code2point.com/Project.aspx?proj=4[^]
 
VBDT
AnswerRe: Events Stop Firing in Win7memberDuddits11-May-11 8:03 
This is a known issue with all low level hooks (mouse and keyboard) in win 7. So this bug has nothing to do with this proposed hooking class here at all.
The solution I discovered for my real world freeware "Transmiti" (www.transmiti.org) is a extra thread which checks permanently the hooks and rehooks automatically in case the hook is lost.
It is an not so easy task as it sounds, because you have to be aware of some important details, like a call to the windows api function SystemParametersInfo with the parameters (SPI_SETBLOCKSENDINPUTRESETS,TRUE,NULL,0) to set the screensaver timer not to be reseted by a virtual keystroke which I send every one second to check the low level keyboard hook.
If you are interested in my real world source I can post some code snippets here.
GeneralAn additional questionmemberambaraba11114-Oct-10 22:43 
Dear VBDT,
 
Now I succed to make your demo working (at home on a Win7), but I am now stucked with the SetWindowsHookEx call when I set he WH_CBT flag.
I got a "Impossible d’établir un hook non local sans un descripteur de module
" message (meaning moreorless: Impossible to set a global hook without a module description).
 
Can I ask you if you can try just to try modify the SetWindowsHookEx call and let me know if you experience any problem?
 
Many thanks in advance
Paolo
GeneralRe: An additional question [modified]memberVBDT16-Oct-10 16:21 
Hi Paolo,
It seems that in framework 4 getting module handle with 'Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);' returns the wrong handle id. This was not a problem in framework 3.5, it seems things got changed or it is a bug in framework 4. Anyways, I changed that line above to an API (GetModuleHandle) function call that gets the right module handle. You can download the updated version of the assembly (1.1.1.3) from 'Download latest version' (my website) link on the top of this page. I don't have the project solution in there but only the code and assembly. If you want the project than you can download it from this page but you need to change the above line to the api function as I have discussed.
 
For installing WH_CBT hook I can only give you a reference link to the (CBTProc) Callback function that you should use to get notifications. Just read the specifications and try to do it. Now I don't have time for it, I am sorry.
 
Good luck!

modified on Saturday, October 16, 2010 10:27 PM

GeneralRe: An additional questionmemberambaraba11118-Oct-10 22:33 
Dear VBDT,
 
first of all, let me thank you for your help.
 
Yesterday, I tried to follow your instructions and the hook now work without any problem.
Then I did a further step and I just changed your hook parameter in the SetWindowsHookEx call where I replaced UnsafeNativeMethods.WH_KEYBOARD_LL with the WH_CBT value.
Unfortunately, as result of this "setup" call, I got a "Impossible d’etabilir un hook non local sans un descripteur de module" (impossible to set a non-local hook without a module descriptor ??)
 
I tried as well with with UnsafeNativeMethods.WH_KEYBOARD param but I got the same.
 
Here I am stucked again, have you another hint?
 
Many thank in advance,
Paolo
GeneralHooking other eventsmemberambaraba1111-Oct-10 1:23 
Hi,
really a great job.
 
I have a question: it is possible as well to make a global hook that intercepts other hook types (e.g. the WH_CBT events)? I would like use it to detect when a new window is opening/closing.
 
I am a little bit confused, because some says that is possible some other don't.
In case, do you have any plan to integrate this in your project?
 
Many thanks in advance,
Paolo
GeneralRe: Hooking other eventsmemberVBDT3-Oct-10 15:35 
Hi Ambaraba111,
Currently I don't have time to add other hooks to the library but the library project is provided so you can extend it if you want.
Check the API SetWindowsHookEx function. This function takes hook type (flag) like WH_CBT which will Install a hook procedure that receives notifications useful to a CBT application.
GeneralRe: Hooking other events [modified]memberambaraba1116-Oct-10 5:20 
Hallo VBDT,
 
thank you for your answer.
 
I started once again from your demo, thet I converted it in VB2010 and c#2010 without any problem.
 
I complied the .DLL project without any hassle and then in the VB project I added a reference to the new DLL (in \bin\x86\Release directory)
 
When I run the application and I hook the mouse, I get an (error) mesaage saying "The operation completed succesfully". The problem is that the hook is not activated (and in the groupbox header it shows "Mouse hook unistalled!"
 
The same happens with the keyboard hook, but it works when I hook the clipboard.
 
I tried as well to point to your original DLL, but the results are the same.
 
I am currently using XP professional version 2002 SP 3
 
Have you any hint? Many thaks in advance
Paolo
 
(update) the problems is in the
this._hMouseHook = UnsafeNativeMethods.SetWindowsHookEx(...)
that returns 0, but I don't know how to make it work ...

modified on Thursday, October 7, 2010 7:49 AM

GeneralKeyhook dllmemberJefry boycot30-Sep-10 19:59 
Hello

Really it’s nice article. Thanks for publish such type of article. It’s really imagine to seen such type of nice article.
I ask small question when I type small 'a' then show capital 'A' as well as when type capital 'A' then also show capital 'A'. Can we difference Capital and small.
GeneralRe: Keyhook dllmemberVBDT3-Oct-10 15:24 
Unfortunately the key down event gets the capital letter code only. The only way to know that the key is lower case or not is to check if the shift key or cops lock keys are down.
GeneralMy vote of 5memberJamal Alqabandi28-Sep-10 1:32 
Perfect

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130617.1 | Last Updated 24 Sep 2010
Article Copyright 2007 by VBDT
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid