Welcome to MSDN Blogs Sign in | Join | Help

Low-Level Keyboard Hook in C#

I answered a question today where someone asked for an example of setting a low-level keyboard hook with C#. I actually have an example of doing so in my May 2006 MSDN Magazine article on Managed Debugging Assistants, but the example is purposefully buggy in order to demonstrate the behavior of certain MDAs.

Here is an example without the bug (compile this as a console application):

using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class InterceptKeys
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private delegate IntPtr LowLevelKeyboardProc(
        int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(
        int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            Console.WriteLine((Keys)vkCode);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Published Wednesday, May 03, 2006 4:29 PM by toub
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

Wednesday, May 03, 2006 5:22 PM by Soumitra Banerjee

# re: Low-Level Keyboard Hook in C#

Hi Stephen,

Do you have anything similiar for low-level mouse hook?

Thanks.
Regards,

Soumitra
Wednesday, May 03, 2006 5:29 PM by Олег Михайлик

# Перехват клавиатурных нажатий на C# [Стивен Тоуб]

Оказывается, это очень просто реализовать. Стивен показывает элементарный пример
Wednesday, May 03, 2006 6:03 PM by Stephen Toub

# Low-Level Mouse Hook in C#

After my last post on implementing low-level keyboard hooks in C#, Soumitra asked if it was possible...
Wednesday, May 03, 2006 6:06 PM by toub

# re: Low-Level Keyboard Hook in C#

Soumitra, I didn't, but the code for doing low-level mouse hooks is almost identical to that for low-level keyboard hooks, so I posted a mouse hooks version for you at http://blogs.msdn.com/toub/archive/2006/05/03/589468.aspx.  Hope it's helpful.
Wednesday, May 03, 2006 6:49 PM by Joku

# re: Low-Level Keyboard Hook in C#

Hey

Great piece of code but it doesn't output anything if I press Alt or AltGr. For all other keys it works.



Wednesday, May 03, 2006 11:25 PM by toub

# re: Low-Level Keyboard Hook in C#

ALT is a system key and won't be handled by the hook because of the filter for WM_KEYDOWN in HookCallback.
Thursday, May 04, 2006 6:09 AM by bg

# re: Low-Level Keyboard Hook in C#

I added a check for WM_SYSKEYDOWN and got the alt and altgr keys

private const int WM_SYSKEYDOWN = 0x0104;

Friday, May 05, 2006 12:02 PM by Jason Haley

# Interesting Finds

Wednesday, May 10, 2006 1:04 PM by Mladen

# re: Low-Level Keyboard Hook in C#

great stuff!

I'm wondering how would you check for a combination of CTRL+V or CTRL+ALT+k or similar?

thanx.
Wednesday, May 10, 2006 5:41 PM by toub

# re: Low-Level Keyboard Hook in C#

System.Windows.Forms.Control.ModifierKeys should do the trick, telling you whether shift, alt, and/or control are pressed.
Thursday, May 11, 2006 5:47 AM by Mladen

# re: Low-Level Keyboard Hook in C#

yes that's true :)
but how would i use them in
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
   // this doesn't work for me
   int vkCode = Marshal.ReadInt32(lParam);
   if ((Keys)vkCode == Keys.C && (Keys)vkCode == Keys.Control)
   {
       Console.WriteLine((Keys)vkCode);
   }  
}

lParam has only one value, no?
so vkCode is also just one value.

What am i missing here??
Thursday, May 11, 2006 8:39 AM by toub

# re: Low-Level Keyboard Hook in C#

if (Keys.C == (Keys)vkCode && Keys.Control == Control.ModifierKeys)
Thursday, May 11, 2006 10:37 AM by mladen

# re: Low-Level Keyboard Hook in C#

thank you very much.

Tuesday, July 11, 2006 4:53 AM by KingOfFotuna

# re: Low-Level Keyboard Hook in C#

Thx, very good code
Wednesday, August 09, 2006 2:34 PM by Dennis

# re: Low-Level Keyboard Hook in C#

Thanks... I have a question.  What would be the best way to take input from an attached device like a barcode reader and capture that information, but provide the application different data?  Thanks in advance
Friday, August 11, 2006 8:42 AM by Serg

# re: Low-Level Keyboard Hook in C#

Thinks, very goo-od!
Sunday, September 10, 2006 9:06 AM by What am I doing wrong?

# re: Low-Level Keyboard Hook in C#

I have tried the code. But I only get this error

C:\Documents and Settings\Thomas\My Documents\Visual Studio Projects\Hooktest\InterceptKeys.cs(10): Method 'InterceptKeys.HookCallback(int, System.IntPtr, System.IntPtr)' referenced without parentheses

complaing on this!
private static LowLevelKeyboardProc _proc = HookCallback;

Sunday, September 10, 2006 11:20 AM by Stephen Toub

# re: Low-Level Keyboard Hook in C#

You're probably using C# 1.x, rather than 2.0.  This code is C# 2.0, making use of delegate inference.
Sunday, September 17, 2006 1:55 PM by Rok

# re: Low-Level Keyboard Hook in C#

How do I have the app "eat" up certain key strokes and not pass it up the chain?

For eg: I'd like to disable the LWin & RWin keys for the duration this program is running.

I tried the following:
switch ((Keys)vkCode)
 {
   // set of keys that should be trapped and nullified
   case Keys.LWin:
   case Keys.RWin:
return CallNextHookEx((IntPtr)0, 0, wParam, (IntPtr)0);
     
   default:
     // pass it along to windows
     return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
Wednesday, September 20, 2006 10:30 AM by Firemaple

# re: Low-Level Keyboard Hook in C#

Is there a way to do the same thing in C#.NET 1.1 (as below) or is not possible?
-----
C:\Documents and Settings\Thomas\My Documents\Visual Studio Projects\Hooktest\InterceptKeys.cs(10): Method 'InterceptKeys.HookCallback(int, System.IntPtr, System.IntPtr)' referenced without parentheses

complaing on this!
private static LowLevelKeyboardProc _proc = HookCallback;
Wednesday, September 20, 2006 10:38 AM by toub

# re: Low-Level Keyboard Hook in C#

Rok, if you want to eat the keystrokes, don't call CallNextHookEx when you receive one of them.

Firemaple, sure, just change that to:

private static LowLevelKeyboardProc _proc = new LowLevelKeyboardProc(HookCallback);

C# 2.0 supports delegate inference (where the compiler knows that I wanted to create an instance of LowLevelKeyboardProc and so doesn't make me type it out), a feature new since 1.1.
Friday, November 10, 2006 11:17 AM by Levi

# re: Low-Level Keyboard Hook in C#

Does anyone know how one would go about getting this to work as a Windows Service?  When running as a service, the event does not seem to fire.  I'm thinking this has something to do with the interactivity of services.

Thursday, November 16, 2006 2:07 AM by SinhTo

# re: Low-Level Keyboard Hook in C#

How can i run KeyboardHook at backgroud and trap all keys at all programs.

Thursday, November 16, 2006 6:38 PM by toub

# re: Low-Level Keyboard Hook in C#

I'm not clear on what you're asking, as the code as it currently exist does intercept the keys for all processes.

Friday, November 17, 2006 10:14 AM by fred

# re: Low-Level Keyboard Hook in C#

i hav created a hook that will allow u to access all users on any network

to do this i just made a hook that allowed u to get all passwords and usernames.

Sunday, December 24, 2006 4:22 PM by Raghavendra

# re: Low-Level Keyboard Hook in C#

Hi,

   This article helped me a lot, presently I am trying to build a MSAA application in c#, there I am using IAccessible object. To get the IAccessble object pointer I need to call the AccessibleObjectFromEvent and need to pass the VARIANT structure. I am stuking here. Can u resolve this problem.

Thanks,

Raghavendra.

Thursday, January 04, 2007 10:33 PM by Beast

# re: Low-Level Keyboard Hook in C#

Cool, works well.

If you have the time can you please advise how I can insert keystrokes into the stream. e.g. What I would like to be able to do is hook my "q" key and  replace it with two "a" key keystrokes

Cheers

Beast

Saturday, January 06, 2007 6:54 PM by toub

# re: Low-Level Keyboard Hook in C#

You can send keystrokes to any app using standard window mechanisms and messages, for example the SendInput function from Win32 or the SendKeys.Send method from Windows Forms.

Tuesday, January 16, 2007 3:57 PM by Joao Ferreira

# re: Low-Level Keyboard Hook in C#

I can't compile, it gives me an error in the "using System.Windows.Forms;" directive. Is there supposed to be this namespace since this is a console program?

Thanks for the code

Tuesday, January 16, 2007 4:01 PM by toub

# re: Low-Level Keyboard Hook in C#

There's no problem in using the Windows Forms DLL from a console app.  If you're getting a compilation error on that line, it's almost certainly because you're not referencing the Windows Forms DLL when you compile.

Tuesday, January 16, 2007 4:09 PM by Joao Ferreira

# re: Low-Level Keyboard Hook in C#

Ah, ok, I got it working now. Sorry for the lame question, still getting accustomed to C#.

Thanks for the quick reply.

Wednesday, January 31, 2007 5:31 PM by Gary Montante

# re: Low-Level Keyboard Hook in C#

Great article!  I'm trying to make a quick & dirty keyboard filter to simplify adding documentation boiler plate to .ASM code.  This way I hope to get my Assembler students to actually do it!

Whenever I use SendKeys.Send(string), the control keys currently in effect are applied to the string by the application.

For example, if Notepad is running, and my filter does something like

if (Keys.C == (Keys)vkCode && Keys.Control == Control.ModifierKeys)

  SendKeys.Send( "hi there" );

Notepad pops up a Replace dialog box because the 'h' in "hi..." is interpreted as Ctrl+h.

Any easy way to turn off the control key for Notepad in this type of case?

Thanks a lot,  G.Montante

Thursday, February 01, 2007 9:32 AM by NewUser

# re: Low-Level Keyboard Hook in C#

Will it work in Vista.  

I don't think so because hooking has some issues because of new Securities problems.

How should all be done in Vista??

Friday, February 02, 2007 4:15 AM by NewUser

# re: Low-Level Keyboard Hook in C#

I don't know what's the reason but I posted this same issue of Vista on many forums but no body use to reply and if some body even reply there is no concrete answer. Everyone revolves around Security Policies or applying XP2 security, but it solves my problem in no way.

Friday, February 02, 2007 2:06 PM by toub

# re: Low-Level Keyboard Hook in C#

NewUser, yes, it should work in Vista, but not in situations where a lower privileged application tries to control a more privileged application; Vista does include security features to prevent such hijacking.

Gary, unfortunately I can't think of any good way to do that without running into a catch-22 situation.  Nice idea, though, and best of lucking finding a solution.

Friday, February 09, 2007 12:07 PM by primo

# re: Low-Level Keyboard Hook in C#

For .Net 1.x, change the Following:

private static LowLevelKeyboardProc _proc;// = HookCallback;

[...]

public static void Main() {

_proc += new LowLevelKeyboardProc(HookCallback);

_hookID = SetHook(_proc);

Application.Run();

UnhookWindowsHookEx(_hookID);

}

Wednesday, February 28, 2007 11:15 AM by rose

# re: Low-Level Keyboard Hook in C#

hi steohen, i have made this code on windows application not in console after fixing error the program results no yhing could you help me please about how to make it working at windows application thanx.

Wednesday, February 28, 2007 11:16 AM by rose

# re: Low-Level Keyboard Hook in C#

hi stephen, i have made this code on windows application not in console after fixing error the program results no thing could you help me please about how to make it working at windows application thanx.

Thursday, March 01, 2007 9:06 AM by Chaosdeckel

# re: Low-Level Keyboard Hook in C#

@Rok:

you can 'return new IntPtr(1);' for the key's you want to block.

Friday, March 02, 2007 4:38 PM by toub

# re: Low-Level Keyboard Hook in C#

Rose, this should work fine in a Windows Forms application as long as you're correctly pumping messages on the thread that installed the hook.  Without knowing more about your code, though, I can't help much.

Friday, March 02, 2007 6:01 PM by Gary

# re: Low-Level Keyboard Hook in C#

Thanks for the code Stephen (and suggestions from others)! I needed to trap the function keys to setup a quick navigation within my application. One thing that I noticed is if you did not return quickly the keypress advances to the next hook and this was a problem as I wanted to display a dialog  on F1 but the next application was getting the event. So I decided to record the key event, setup a timer for 100ms and process the key event when the timer is raised. This allows for immediate return of (1) which consumes the key press as desired. I hope this helps, and if anyone has a better method please let me know. Cheers Gary.

Thursday, March 15, 2007 3:35 AM by Ravikanth

# re: Low-Level Keyboard Hook in C#

Hi Stephen,

Actually i am looking to develop a windows service with similar functionality.

For ex. if i press key "s" it should save a image.

so from the service ""onstart" method i am calling something like this

myKeys.RegisterKeyBoardHook();where myKeys is the object of InterceptKeys class and written

public void RegisterKeyBoardHook()

       {

            <Check to see whether the code pressed is S>

{

           _hookID = SetHook(_proc);

           StoreImage();

}

       } in the InterceptKeys class.

But when i press the key "s" storeImage is not getting called..

Any help on this..

Regards,

Ravikanth

Thursday, March 15, 2007 10:38 AM by Ravikanth

# re: Low-Level Keyboard Hook in C#

Hi Stephan,

Though Its a very worthy article,

I am left over with a question.

private static IntPtr HookCallback(

           int nCode, IntPtr wParam, IntPtr lParam)

       {

           if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))

           {

               int vkSCode = Marshal.ReadInt32(lParam);

if (((Keys)(Keys.S)) == (Keys)vkSCode && ((Keys)(Keys.Control | Keys.Alt) == Control.ModifierKeys))

               {

                  StoreImage();

               }

           }

           return CallNextHookEx(_hookID, nCode, wParam, lParam);

       }

using the above code snippet i am able to trap CTRL+ALT+S

How can i implement CTRL+ALT+S+L ??Bcoz there will be only one lParam...

Can you please reply me fast..

Regards,

Ravikanth

Thursday, March 15, 2007 10:46 AM by toub

# re: Low-Level Keyboard Hook in C#

Watch for both WM_KEYDOWN and WM_KEYUP for both keys.  You'll need to look for receiving a WM_KEYDOWN for S and one for L before you receive a WM_KEYUP for whatever was received first.  You won't just get one event, because there are truly multiple keystrokes here.

Thursday, March 15, 2007 11:50 AM by Ravikanth

# re: Low-Level Keyboard Hook in C#

Hi Stephan,

I written the code as below..

if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))

           {

if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))

{

 int vkCode = Marshal.ReadInt32(lParam);

 if (((Keys)(Keys.S)) == (Keys)vkCode)

     keySPressed = true;

 if (((Keys)(Keys.L)) == (Keys)vkCode)

     keyLPressed = true;

 if (keySPressed && keyLPressed && ((Keys)(Keys.Control | Keys.Alt) == Control.ModifierKeys))

                   {

                       StoreImage();

                   }

               }

               else if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP))

               {

                   keySPressed = false;

                   keyLPressed = false;

               }

           }

           return CallNextHookEx(_hookID, nCode, wParam, lParam);

       }

But still i am getting lot of calls to "StoreImage".

Where i am going wrong ???

Thursday, March 15, 2007 12:58 PM by toub

# re: Low-Level Keyboard Hook in C#

I don't follow the logic you're using.  You could try something like the following, though I haven't tested it.  In general, I'm happy to try to help when I have time, but I don't have time right now to debug random code.

private static bool keySPressed, keyLPressed;

private static bool ControlAltPressed

{

   get

   {

       Keys mods = Keys.Control | Keys.Alt;

       return (Control.ModifierKeys & mods) == mods;

   }

}

private static IntPtr HookCallback(

   int nCode, IntPtr wParam, IntPtr lParam)

{

   Keys key = (Keys)Marshal.ReadInt32(lParam);

   if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)

   {

       if (key == Keys.S && ControlAltPressed) keySPressed = true;

       if (key == Keys.L && ControlAltPressed) keyLPressed = true;

       if (keySPressed && keyLPressed) Console.WriteLine("Pressed");

   }

   else if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)

   {

       if (key == Keys.S) keySPressed = false;

       if (key == Keys.L) keyLPressed = false;

   }

   return CallNextHookEx(_hookID, nCode, wParam, lParam);

}

Thursday, March 15, 2007 1:01 PM by toub

# re: Low-Level Keyboard Hook in C#

Note, too, that the above sample won't catch all corner cases. For example, keySPressed and keyLPressed will remain true even if the user lets go of the Control or Alt keys (while still continuing to hold S and L).

Sunday, April 15, 2007 12:05 PM by John

# re: Low-Level Keyboard Hook in C#

hi stephen

do you have anything similar for the PocketPC

regards

john

Friday, April 20, 2007 3:45 PM by Phillip Pearce

# re: Low-Level Keyboard Hook in C#

Hi Stephan,

This is a more general question regarding local hooks. Is it possible to create local hooks for other applications present on the desktop, assuming I know thre thread id of this application?

Thanks

Phillip

Friday, April 20, 2007 3:46 PM by Phillip Pearce

# re: Low-Level Keyboard Hook in C#

Hi Stephan,

This is a more general question regarding local hooks. Is it possible to create local hooks for other applications present on the desktop, assuming I know the thread id of this application?

Thanks

Phillip

Friday, April 20, 2007 4:34 PM by joe

# re: Low-Level Keyboard Hook in C#

Is there a way to just intercept for current process key press?  The sample code catch all process key action, right?

Thanks,

joe

Saturday, April 21, 2007 5:16 PM by toub

# re: Low-Level Keyboard Hook in C#

Joe: Sure, see http://support.microsoft.com/kb/318804.  The example traps mouse events, but the code for keyboard events is similar.  If you search the Web, you'll find a bunch of additional examples.

Philip: You can either create a local hook (just the current process) or a global hook (every process).  If you create a global hook, when you receive an event, you can do things like check what window is currently in the foreground to deduce what app will be processing the message, and filter based on that.

Monday, April 23, 2007 9:35 AM by Phillip

# re: Low-Level Keyboard Hook in C#

Stephen...

So its either local on the current process only OR global on all processes.

I have an accounting application that I want to hook and subsequently trap keystrokes to add additional functionalty. I invoked the applications executable using the 'CreateProcess' API, obtained the thread id and defined my hook(s) based on that but the SetWindowsHookEx function failed!

Is this approach not possible based on your definition of what you can hook?

Thanks

Phillip.

Monday, April 23, 2007 10:51 AM by toub

# re: Low-Level Keyboard Hook in C#

From the documentation:

"The global hooks are a shared resource, and installing one affects all applications in the same desktop as the calling thread."

Additionally, most global hooks can't be used from .NET... from support.microsoft.com/kb/318804:

"Except for the WH_KEYBOARD_LL low-level hook and the WH_MOUSE_LL low-level hook, you cannot implement global hooks in the Microsoft .NET Framework. To install a global hook, a hook must have a native DLL export to inject itself in another process that requires a valid, consistent function to call into. This behavior requires a DLL export. The .NET Framework does not support DLL exports. Managed code has no concept of a consistent value for a function pointer because these function pointers are proxies that are built dynamically."

Monday, April 23, 2007 10:58 AM by Phillip

# re: Low-Level Keyboard Hook in C#

Thanks. Yes, I was aware of the limitations,  costs (performance) and 'danger' of global hooks in .NET, which is why my first choice would have been a local hook.

I guess you are saying that I cannot define a hook using the thread id from another process - is that correct?

Thanks

Phillip.

Monday, April 23, 2007 11:20 AM by toub

# re: Low-Level Keyboard Hook in C#

The only global hooks that work with .NET (due to the injection issue mentioned previously) are WH_KEYBOARD_LL and WH_MOUSE_LL, and those can't be associated with a particular thread in another app; if you try, you'll get back  Win32 error 0x0595: "This hook procedure can only be set globally".

Monday, April 23, 2007 11:57 AM by Phillip

# re: Low-Level Keyboard Hook in C#

Okay. I understand the limitations on the scope of global hooks, however that is really not the way I actually want to go anyway.

My question was really on local hooks and whether you could use the thread id from another process to define your hook.

I guess you are saying you cannot do this and you are suggesting global hooks as an alternative - but bearing in mind their limitations in .NET.

Thanks

Phillip.

Sunday, May 06, 2007 5:01 AM by Ran Sagy

# re: Low-Level Keyboard Hook in C#

Thanks for this sample. I needed something similar for a small project I'm doing (basically grab keyboard strokes, And pastes info into the clipboard based on which application was active when the keypress was made), And this does the trick. Too bad the .NET API is still missing many native calls needed. Hopefully, By Orcas it will get better.

Wednesday, May 09, 2007 11:59 AM by Dan

# re: Low-Level Keyboard Hook in C#

Hey Stephen,

Thanks for the code, but I have one problem though.

I have been trying to use the code in a WINFX .NET 3.0 project and I have managed to get it to work by adding System.Windows.Input to the namespace and changing Keys to Key as in:

int vkCode = Marshal.ReadInt32(lParam);

MessageBox.Show(Convert.ToString((Key)vkCode));

It debugs the project fine but when it comes to pressing a key, rather than showing a D, it outputs a Y instead.

Any ideas?

Thanks

Wednesday, May 09, 2007 12:15 PM by toub

# re: Low-Level Keyboard Hook in C#

The System.Windows.Forms.Keys and System.Windows.Input.Key enumerations have different values (Keys.D == 0x44, Keys.Y == 0x59, Key.D == 0x2F, and Key.Y = 0x44).  The former maps more directly to virtual key codes.  If you're using WPF, you can use the public static method System.Windows.Input.KeyInterop.KeyFromVirtualKey to convert vkCode into a Key value.

-Stephen

Wednesday, May 09, 2007 12:26 PM by Dan

# re: Low-Level Keyboard Hook in C#

Ah right. Thanks for your help! :)

- Dan

Sunday, May 20, 2007 2:58 AM by Arif

# re: Low-Level Keyboard Hook in C#

Hey All,

Great article and useful converstations! I was able to hookup the keyboard to a local process (using the WH_KEYBOARD [=0x02] hook and passing the process id to the SetWindowsHookEx API) and also by using Philips timer idea, was able to cache and control the key strokes.

Thanks all for the help;

- Arif

Monday, June 04, 2007 1:24 PM by toub

# re: Low-Level Keyboard Hook in C#

What do you mean "this isn't working"?  How exactly is it not working?  Are you getting a compiler error?  Is it throwing an exception? etc.

Wednesday, June 06, 2007 2:44 AM by reesylou

# re: Low-Level Keyboard Hook in C#

Firstly... wonderful piece of code.  

I am building a Keyboard Basher for my baby daughter, and as such want to detect and redirect several keystrokes (like LWin and RWin).

Using your sample as part of a Windows form, I have no problem detecting and consuming these keys, but what if I want to act on them (and still not pass them on to the system)?  How do I workaround not being able to call a non-static method directly in this code?

Wednesday, June 06, 2007 2:46 AM by reesylou

# re: Low-Level Keyboard Hook in C#

(PS I am using .NET 1.1 and have adapted the code accordingly based on your previous comments)

Sunday, June 10, 2007 5:20 PM by Igor Gatis

# re: Low-Level Keyboard Hook in C#

I'm using your code to launch an very simple app that allows to copy code snippets from anywhere. It works just fine until I right click on the app tray icon to access its menu. After that, it does fire keyboard events to my app anymore (like it was unhooked).

Is it expected? Or am I doing something that's causing this?

Monday, June 11, 2007 5:14 AM by Igor Gatis

# re: Low-Level Keyboard Hook in C#

One more thing: I'm using Vista 64-bit.

Friday, June 15, 2007 6:08 PM by Varix

# re: Low-Level Keyboard Hook in C#

Im doing a similar hook in Delphi. I understand that the style is different from c#. I have a basic hook, but it actually traps the keys. I would like them to be read, but still passed on to the application that has focus. How would i do that?

Friday, June 15, 2007 11:47 PM by toub

# re: Low-Level Keyboard Hook in C#

Varix, just make sure to call CallNextHookEx in all places where you want the keys passed along.

Monday, July 23, 2007 11:57 PM by guyc

# re: Low-Level Keyboard Hook in C#

Will this hook work with 3d games that use Directx?

Friday, August 03, 2007 6:49 PM by Derek

# re: Low-Level Keyboard Hook in C#

Great code. Thank you very much.

Saturday, August 04, 2007 6:41 AM by evrastil

# re: Low-Level Keyboard Hook in C#

Hi Stephen great code...

I have a question. I see that Im not alone, because people asked here before, but no answer...

Does anyone know how one would go about getting this to work as a Windows Service?  When running as a service, the event does not seem to fire. Can you help Stephen or anyone?

Monday, August 06, 2007 11:29 AM by Flood

# re: Low-Level Keyboard Hook in C#

Hi all

Good stuff Stephen and contributers also.

I did have the same question as evrastil about running this as a windows service... any ideas or pointers?

Thank you,

Monday, August 06, 2007 11:40 AM by toub

# re: Low-Level Keyboard Hook in C#

Tuesday, August 28, 2007 1:37 AM by Jonathan

# re: Low-Level Keyboard Hook in C#

How in .NET framework 2.0 do I convert the Integer keyCode or IntPtr lParam value to the actual value entered by the user, not one of the Keys enumerators?

Wednesday, September 05, 2007 4:26 AM by Russell

# re: Low-Level Keyboard Hook in C#

Hi,

First of thanks to Stephen Toub for the code. Currently my PC is running an app that changes mode if I press the F12 key. If I run your program it shows all keys except the F12 key (probably that program not passing it up to next hook as eating it up?). How can I make sure that your program first traps the F12 rather than that program? Although my ultimate goal is to not trap the event rather send/generate the F12 keystrokes from my program to change the mode (SendInput using user32.dll does not work, so I think it is using low level hook or something?) of that program using code.

Thanks

Wednesday, September 05, 2007 5:11 PM by Ed

# re: Low-Level Keyboard Hook in C#

Hi,

I'm having the same problem Joao had back Jan. 16: I get the error in "using System.Windows.Forms."  Apparently he got it to work, but I don't understand the solution.  How does one refrence the Windows Forms DLL when compiling?

I'm a real noob with C# and I'm using Visual C# 2005 Express.

Thanks,

Ed

Thursday, September 06, 2007 12:03 AM by Ed

# re: Low-Level Keyboard Hook in C#

Duh.  I found the problem.  I needed to add

System.Windows.Forms to the references in the Solution Explorer in Visual C# Express.

Thanks for the great code, Stephen!

Ed

Monday, September 10, 2007 2:06 PM by mike

# re: Low-Level Keyboard Hook in C#

Hi Stephen, Will this code work in the Windows Compact Framework?  Im guessing using coredll.dll instead of user32.dll might work for some of those unmanaged commands but im not sure how that would translate with the rest of the code.

Thanks,

Mike

Thursday, September 20, 2007 4:52 AM by Jon

# re: Low-Level Keyboard Hook in C#

Do you know of any more forums related to this topic and a windows service?  I've tried the above links and can't find a solution.

I wish to temporarily disable the windows and alt+tab system keys which I can't trap in my app. This occurs while a form is visible and then is released when the form is hidden.

My service already runs interactively (hence the form appearing), which is a proposed solution on one of the forums.

Many thanks for any help on this

Thursday, September 20, 2007 9:01 AM by Naveen

# re: Low-Level Keyboard Hook in C#

i'm using ur code for low-level keyboard hook

but the above code throw an error

"namespace name 'Process' could not be found"

even after importing all the namespaced

can u plz help me in finding solution

thanks

Naveen Kushwaha

naveenkushwaha@gmail.com

Tuesday, October 09, 2007 5:35 AM by bob builder

# re: Low-Level Keyboard Hook in C#

Hello.. How can I differ between capital letter, other languages letters and regular letters

i.e :

c and C will give me the same results.

also for every other key like b and B.

Thanks!

Tuesday, October 09, 2007 9:48 AM by toub

# re: Low-Level Keyboard Hook in C#

Bob, you can use GetKeyState from user32.dll to check the status of the shift key, for example.

Wednesday, October 10, 2007 3:59 PM by bob builder

# re: Low-Level Keyboard Hook in C#

But it doesn't gets me if it's other languags.

also, if caps lock were hitted it doesn't give me the state.

I would like to know which letter has been typed in Hebrew.

Wednesday, October 17, 2007 7:17 AM by ShaMirza

# re: Low-Level Keyboard Hook in C#

Any solution which make this work on vista.

Saturday, October 20, 2007 6:40 AM by xiaojiuhk

# re: Low-Level Keyboard Hook in C#

Thank you, bur the code is too short , I am suspicions of its function.

Tuesday, October 23, 2007 12:12 PM by SHA MIRZA SUNQUEST EMPLOYEE

# re: Low-Level Keyboard Hook in C#

Update: I finally resolved this. The code was using the WH_KEYBOARD flag. When run under Vista, the call to SetWindowsHookEx () would fail with a NULL return code. I changed the flag to WH_KEYBOARD_LL and Vista (and other platforms) are once again happy.

Wednesday, January 02, 2008 4:30 PM by jon

# re: Low-Level Keyboard Hook in C#

Hey, i want to 'eat up' keys, but your suggestion of not calling CallNextHookEx isn't working. other applications receive input. any other ideas?

Sunday, January 06, 2008 11:35 PM by hunter

# re: Low-Level Keyboard Hook in C#

In HookCallback(), instead of returning nothing or the original value how can I return another key value? For example if 'j' was pressed how can I change it so that 'k' was pressed?

Sunday, January 06, 2008 11:35 PM by hunter

# re: Low-Level Keyboard Hook in C#

In HookCallback(), instead of returning nothing or the original value how can I return another key value? For example if 'j' was pressed how can I change it so that 'k' was pressed?

Monday, January 07, 2008 9:15 AM by Hezi

# re: Low-Level Keyboard Hook in C#

Hi,

How can I trap Alt+Tab keys? A similar question has been asked already by Jon on September 20 2007 but I Didn't fined an answer.

Thanks,

Hezi

Thursday, January 10, 2008 3:44 PM by Stephan

# re: Low-Level Keyboard Hook in C#

I don't know if it is exactly the same ... I want to exchange keypresses like user pressed X but it is replaced with Y.

I need it in a way that the following events get the replaced value.

this should work like this

user presses X >>>

1. replace event is called X is replaced with Y

2. KeyDown with "Y"

3. KeyPress with "Y"

4. KeyUp with "Y"

Friday, January 11, 2008 4:19 PM by Matt

# re: Low-Level Keyboard Hook in C#

Stephen,

Thanks for providing your code and keeping up with all the comments/questions that people have added.  That's very cool of you.

I have another question.

I'm using your code - along with the other example you gave for listening to mouse events - to detect whether my windows forms app is currently in use.  I'm only interested in events from MY app/process, but when I pass-in the thread id for the current thread, the hook doesn't work.

Also, when I just pass in zero as the thread id, my little test app is slow to close (3 or 4 sec compared to almost-instantaneous when the hooks aren't there).  I assume this is b/c it's listening for events from all processes.

So my question is: how can I set the listener to listen to my app/process only?  Or, if that's not possible, how can I speed things up?

Thanks in advance.

-Matt

Saturday, January 12, 2008 8:41 PM by toub

# re: Low-Level Keyboard Hook in C#

Jon, if your goal is to eat the input (not calling CallNextHookEx), make sure you return (IntPtr)1 from the hook callback rather than IntPtr.Zero.

Hezi, the code as I have it is looking only for WM_KEYDOWN messages... for alt, you also need WM_SYSKEYDOWN.

Hunter and Stephan, see http://support.microsoft.com/kb/33690.

Matt, for an example of setting a hook only for the current process, see http://support.microsoft.com/kb/318804.

Tuesday, January 15, 2008 8:00 PM by Morten Gregersen

# re: Low-Level Keyboard Hook in C#

Is there anyway, to get the code to write the localized names of the keys out? When I press on "ÆØÅ" (three Danish letters) it says Oemtilde, Oem7 and Oem6.

Another thing: Is it possible to get the code not to register the key several times because it is pressed down for a while, so it only tracks the key once everytime you press and 'unpress'?

Friday, January 18, 2008 1:21 PM by Morten Gregersen

# re: Low-Level Keyboard Hook in C#

I got the keydown fixed! :D Just changed the KEYDOWN to KEYUP and changed the 0x-thingy.

I still haven't figured out how to use a specific keyboard layout... :(

Sunday, January 20, 2008 10:33 AM by Raveheart

# re: Low-Level Keyboard Hook in C#

I also can't get this to run as a service, even allowing for interaction with the desktop. All I'm trying to do is get the time of the very last input on an XP machine (with multiple fast user-switching logins). I need to know if any user is still active so my service can react appropriately. Very grateful for any suggestions/comments.

Monday, February 04, 2008 4:22 AM by aalan

# re: Low-Level Keyboard Hook in C#

Hi Stephen,

Do you have anything similiar for low-level mouse hook?

Thanks.

Monday, February 04, 2008 11:51 AM by toub

# re: Low-Level Keyboard Hook in C#

Wednesday, February 20, 2008 6:48 AM by Nik

# re: Low-Level Keyboard Hook in C#

Stephen just wanted to thank you for all the hard work you have put in and for the patience while replying back to the questions.

Keep up the good work guys!

Saturday, February 23, 2008 7:37 AM by Caspian

# re: Low-Level Keyboard Hook in C#

Hi - I'm trying to compile your program using Microsoft Visual C# Express Edition, but I get an error in the build process - it says  'The type or namespace name 'Windows' does not exist in the namespace 'System' (are you missing an assembly reference?)'

How do I use an assembly reference?

Thanks,

Caspian

Monday, February 25, 2008 11:52 AM by Mark

# re: Low-Level Keyboard Hook in C#

Hi toub, great code!

how to know the difference between eg. a (lowercase) and A (Uppercase)?

the same for other( b,B; c,C and so on...)

thnk a lot

Mark

Tuesday, February 26, 2008 2:40 AM by toub

# re: Low-Level Keyboard Hook in C#

You can use GetKeyState from user32.dll to determine the state of the shift key and the caps lock key.  Alternatively, you can use Control.ModifierKeys to get the state of the shift key and Console.CapsLock to get the state of the caps lock key; internally, they just use GetKeyState.

Friday, March 07, 2008 5:29 AM by kooldude

# re: Low-Level Keyboard Hook in C#

Hi,

I want to hook Fn+ keys. For ex Fn+F1..F10.

Please advise How to go about it.

Thanks a lot.

Friday, March 28, 2008 1:32 AM by naren

# re: Low-Level Keyboard Hook in C#

i want hook for toggling windows

Tuesday, April 08, 2008 6:57 PM by RickyS

# re: Low-Level Keyboard Hook in C#

Stephen and Gary,

I notice a couple of comments about the issue sendkeys with the control key.  I'm getting as Gary mentioned, the control (and alt) keys in addition to my send key string.  Can either of you elaborate on the cause and workaround / solution for this situation.

Thanks for this great article and thread!

Ricky

Wednesday, April 23, 2008 5:55 AM by Low-Level keyboard hooks in VB.NET &laquo; Rodger Benham

# Low-Level keyboard hooks in VB.NET &laquo; Rodger Benham

Thursday, May 08, 2008 6:28 AM by eddie

# re: Low-Level Keyboard Hook in C#

I am having trouble capturing shift+{any kay} when it is pressed in continuous manner.

It goes like this..

1. You press shift+a

2. Release the 'a' key but dont release the shift key.

3. Press 'b'. Here the program is supposed to capture shift+b but it only captures b.

I am using GetAsyncKeyState to get the status of shift key. If I release the shift key at step 2 above, the program capture shift+b fine.

Am I missing something here?

Saturday, May 10, 2008 5:41 AM by asnat

# re: Low-Level Keyboard Hook in C#

hello

i have a problem which seems a bit strange.

i have a small program that do the follow:

if (vkCode == key) sendkey.sendwait("^c");

when the key is the CTRL key the program runs well. if it's a shift it doesn't.

any idea?

Friday, May 16, 2008 11:41 AM by sudheer

# re: Low-Level Keyboard Hook in C#

Hi,

I want to do something on when key down and also on key up.

like

onKeyDown()

{

///do some thing

}

onKeyUp()

{

///do some thing

}

I am not familiar with c# and .net please can you help me out.

Friday, May 16, 2008 5:17 PM by Lasse

# re: Low-Level Keyboard Hook in C#

Hi.

Is there any possibility to place the self-defined hook procedure at the end of the hook chain?

E.g. if I monitor keyboard strokes and identify a 'ctrl+c' my hook fires before the copy-action (resulting from ctrl+c) starts. Is it possible to have my hook fire after this copy action?

Thanks in advance.

Cheers, Lasse.

Friday, May 16, 2008 6:38 PM by s sharp

# re: Low-Level Keyboard Hook in C#

I am having trouble capturing shift+{any kay}

Friday, May 30, 2008 9:58 AM by Sebastiano

# re: Low-Level Keyboard Hook in C#

I'm trying do send keys to a directx application (mictosoft train simulator), the classic sendkey doesn't work....

I tryed to see if there's something in the directx to emulate a keypress, but i still haven't found anything.

Please help me!!

Wednesday, June 04, 2008 10:34 AM by Brandon

# re: Low-Level Keyboard Hook in C#

Thank you so much this works like a dream. You dont know how much this just helped me!!!

Friday, June 20, 2008 1:05 PM by chan

# re: Low-Level Keyboard Hook in C#

Is there a way to capture keys from multimedia keyboard?

I able to capture all keys except these keys "PLAY","PAUSE", "FORWARD", "REVERSE","HOME", and "POWER".

Thank you for your hard work.

Saturday, June 21, 2008 2:58 PM by Nicholas

# TIMER problem

Hello! Thank you for this great piece of code! It helped me a lot. Using the program above, I'm "recording" the keys pressed into a file. Everything is ok, I am able to handle situations when Shift or Caps are pressed.

My question: How can I implement a timer so the file gets empty between a specific interval  (example: every 10 min. the file is emptied)?

I don't know where should I declare the timer. I tried to declare it in Main(), something like:

<code>

_hookID = SetHook(_proc);

System.Timers.Timer timer = new System.Timers.Timer(30000);

timer.Elapsed += new ElapsedEventHandler(anotherclass.OnTimedEvent);

  timer.Enabled = true;

Application.Run();

UnhookWindowsHookEx(_hookID);

<code>

The code above works just ONCE! The file gets emptied once...

Thank you. I hope you will reply soon.

Nicholas

Monday, June 23, 2008 4:37 AM by Nicholas

# re: Low-Level Keyboard Hook in C#

Hi! Me again... The timer works fine, there was a problem somewhere else in my code... Thanks anyway.

Nicholas

Wednesday, June 25, 2008 5:00 PM by Bhavesh

# re: Low-Level Keyboard Hook in C#

kool application... this is what i was looking for from long time

Tuesday, July 01, 2008 10:34 AM by ibrahim

# re: Low-Level Keyboard Hook in C#

Hey, why you use Application.Run() to call the HookCallback() method. Unfortunately, i got an error "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." when i suppose to call the "HookCallback()" method without Application.Run().

The error shows in the following code,

return CallNextHookEx(_hookID, nCode, wParam, lParam);

i'm using another form in my program, hence i need to call "HookCallback()" method without "Application.Run".

Is there any way to do like this....

Monday, July 07, 2008 8:10 AM by yosi

# re: Low-Level Keyboard Hook in C#

hi! i am wating for an answer. how can i add a new item to the pop-up menu of the computer(right click).

thanks,

Thursday, July 10, 2008 12:19 AM by HauLD

# re: Low-Level Keyboard Hook in C#

It's very useful code. Thank you a lot.

Tuesday, July 22, 2008 11:45 AM by Attila Pápai

# re: Low-Level Keyboard Hook in C#

Hello All!

I am making a service application which logging user activites like mouse moving and key pressing and here comes Hooks. First of all I tried it in a console application and everything was perfect, but when I put the code (and some other) to the service app. and started it, nothing happened. I am sure the code is good. I am running the service in the background with Local System privileges.

Is there anybody can help me?

Thanks!!

Wednesday, July 23, 2008 9:04 AM by Attila Pápai

# re: Low-Level Keyboard Hook in C#

Okey, I found the way to this.

Here is the code:

put it in AfterInstall:

RegistryKey ckey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\nServiceName",true);

           if (ckey != null)

           {

               if (ckey.GetValue("Type") != null)

               {

                   ckey.SetValue("Type", ((int)ckey.GetValue("Type") | 272));

                }

             }

Saturday, August 09, 2008 1:09 AM by Chris P

# re: Low-Level Keyboard Hook in C#

Hello.  I'm working on this bit as a windows service as well, in a Vista 32-bit environment.  Unfortunately, this all works well and good until I run it as a service.  Then it's all failure.  I noticed my service will actually briefly catch keys after the installer runs, but shortly after it's shutdown and when I launch it from my services panel I get nothing.  I tried the above mentioned fix, setting my type value to 272, but no avail.  Has anyone else found a way around the Windows Service limitations?

Tuesday, August 19, 2008 3:33 PM by Amelie

# re: Low-Level Keyboard Hook in C#

Hi Toub,

I have a simple question:

Your code captures all key presses globally, right? Is there a way to limit those to a single application, like a way to specify in the hook so that key presses are only captured if that application is in focus?

Also do you know how to detect if shift/alt/control keys are pressed? I would like to add these info separately to the eventargs. Should I convert the keycode into Keys? If so, how? Because I am writing a DLL, not exe.

Thanks.

Sunday, August 24, 2008 10:06 AM by ламинат

# Ламинат цены

4gGood idea.2f I compleatly disagree with last post .  nir

<a href="http://skuper.ru">ламинат купить</a> 6r

Thursday, August 28, 2008 1:35 PM by Darkonekt

# re: Low-Level Keyboard Hook in C#

Hey i have written code that works perfect on windows and console apps that check all kinds of key combos and it works wonderful. But when i run it inside a service it wont work. This is my opinion services run under a different user session and therefore they catch keystrokes for that user only under which they are running. Now my question is: has anyone had the hook working under a service? If so can you please show us. I have tried a million things and nothing works. Also has anyone been able to run a .NET DLL under svchost? May be thats the answer. I havent been able to do neither one.

Saturday, September 13, 2008 9:16 AM by Abraham

# re: Low-Level Keyboard Hook in C#

Hi, this is a great start for me - a newbie.

I have a java program that programatically toggles the Caps Lock key.  Is there a way to allow the 'programatic key strokes' but block the actual key strokes from the keyboard?

Any advice at all would be gratefuly received.

Regards

Abe

Monday, September 29, 2008 1:44 PM by Anil

# re: Low-Level Keyboard Hook in C#

Do you have a code to cature key board ket events using window service without using form.

Could you please suggest me where can I find this code

Thanks

Anil

AnilM@ForBiztech.com

Monday, October 20, 2008 8:57 PM by Richard

# re: Low-Level Keyboard Hook in C#

Hi, have you ever tried to use comments in your code? I think they are fundamental.

Friday, October 24, 2008 11:24 PM by starspace

# Low-level Windows API hooks from C# to stop unwanted keystrokes

Sunday, November 09, 2008 9:14 AM by jordanwb

# re: Low-Level Keyboard Hook in C#

How would I use this in a Windows Form Application?

Thursday, November 13, 2008 3:00 PM by Argon

# re: Low-Level Keyboard Hook in C#

Works almost perfect, just for a detail, I opened a instance of notepad and when I tried to close it, takes a lot to close.

Any suggestions?

Sunday, November 16, 2008 11:36 PM by Pramod.dev

# Is there any way to intercept caps lock without interop

I have a requirement to alert user that caps key is on. And i dont want to use any heavy interop. Is there any other way to do this.

Regards,

Pramod Pallath Vasudevan.

Sunday, January 18, 2009 12:12 PM by KeyPress in Word | keyongtech

# KeyPress in Word | keyongtech

Wednesday, January 21, 2009 12:30 PM by Shortcut key globale ? | hilpers

# Shortcut key globale ? | hilpers

Thursday, February 05, 2009 6:32 PM by Keylogger in C# :: Introduction - Axino.net

# Keylogger in C# :: Introduction - Axino.net

Friday, February 06, 2009 2:17 PM by semir

# re: Low-Level Keyboard Hook in C#

Please can someone tell me how to make keyboard hook from windows service? I was trying to allow interact width desktop but it is not working and I don't get any exception...??

Saturday, February 07, 2009 7:48 PM by ttomsen

# re: Low-Level Keyboard Hook in C#

The reason this is not working in an windows app is the line :

Application.Run()

Then the very next line unhooks the hook.

So i removed the application run, i put the hook close in the formClosed event.

This works, however my call back is being called twice now?

Tuesday, February 10, 2009 8:49 AM by Bruce

# re: Low-Level Keyboard Hook in C#

Stephen, I'm writing a service that catch all printscreen and save the image in a directory.

My SendHook returns a number, but my HookCallback not respond to any click. Can you help me?

Wednesday, February 18, 2009 4:50 PM by La Dai Dong

# re: Low-Level Keyboard Hook in C#

Thanks much for your code.

I'm modified it as an Class. Now I can use it like this:

KeyHook newKeyTrap = new KeyHook();

//IMPORTANT - Set Even Handle for KeyHook Return Event

newKeyTrap.keyHookReturn += new KeyHook.KeyHookReturn(HookReturn);

newKeyTrap.Start();

private void HookReturn(int keyEvent, int vkCode)

{

      //Do Any things with vkCode

      //You can use System.Windows.Forms.Keys class to check any button is pressed included Multi Media Key

      //If you don't know the name of that button in Keys Class just write out the vkCode and Find for that code in Keys Class

}

My Code also can detect which Window is focus in (By the Window Title)

Email me if You interested in My Code.

ladaidong@yahoo.com

Friday, February 20, 2009 3:00 AM by Luiz Roberto

# re: Low-Level Keyboard Hook in C#

Thank you very much for your code.

3 years later still helping peoples.

Saturday, February 21, 2009 12:12 PM by Обои

# re: Low-Level Keyboard Hook in C#

thanx for the interesting posts

Tuesday, February 24, 2009 6:14 AM by woop

# re: Low-Level Keyboard Hook in C#

awesome piece of code. Cheers!

Wednesday, March 04, 2009 3:28 AM by Akshay

# re: Low-Level Keyboard Hook in C#

i have a requirement where i need to create a virtual keyboard and its keys should change on the culture of c# code.

Ao if  A S D F keys are in english keyboard then if i change the culture to french it should show me French keyboard keys in place of  A S D F it should start showing Q S D F

does anyone knows how to do that.

Thursday, April 02, 2009 9:40 AM by Rem@ - блог .NET

# Отслеживаем события в Вашем .NET приложении

Возникла сегодня задача... Сделать возможность приложению реагировать на нажатие клавиш. Ничего сложного

Monday, April 06, 2009 10:55 PM by janardhan

# re: Low-Level Keyboard Hook in C#

hello....when i compile this code, i'm getting..." Error 1 'WindowsFormsApplication1.Form1.Dispose(bool)': no suitable method found to override " ....i just copy pasted the above code to a new forms application...what do i have to do to make this code work?

Wednesday, May 06, 2009 9:08 PM by Amarpreet Singh

# re: Low-Level Keyboard Hook in C#

Great Post Dear

I was looking exactly the same thing you did.

Thanks.

Keep it up.

Wednesday, June 10, 2009 3:39 AM by ankush

# re: Low-Level Keyboard Hook in C#

hi Stephan

can you help me. actually i am working on a window application using c#, i wanna know how to capture keystrokes when my window application is active, i wanna know that how to capture keystrokes with source application, please help me out . thanks

Saturday, June 13, 2009 4:00 AM by ankush

# re: Low-Level Keyboard Hook in C#

hi Stephan

can you help me. actually i am working on a window application using c#, i wanna know how to capture keystrokes when my window application is active, i wanna know that how to capture keystrokes with source application, please help me out . thanks

Thursday, June 25, 2009 3:17 AM by Amit R

# re: Low-Level Keyboard Hook in C#

Hi Stephan,

Great post.

I have question about Windows Mobile development.

Can we use the same code into the Windows Mobile application? If yes, then what about the OEM keys?

Thanks.

Regards,

Amit Rote

Thursday, June 25, 2009 9:01 AM by Andy Bantly

# Mouse / Keyboard Hook in C++ 2005

How to create a keyboard and mouse hook in Visual C++ 2005

Step 1: Create a CWinThread derived thread to house the hook procedures.  The documentation tells us that hook procedures can have global or thread state.  We are interested in thread state so we place our hook in a thread and then hook the Thread ID of the main .EXE, which can be DOC/VIEW or Dialog based.

Step 2: Instantiate the thread that contains the hook in the application.

Step 1 Code

#define WM_ENDTHREAD WM_APP + 100

// CHookThread

class CHookThread : public CWinThread

{

DECLARE_DYNCREATE(CHookThread)

public:

CHookThread(int iThreadId = GetCurrentThreadId());

virtual ~CHookThread();

virtual BOOL InitInstance();

virtual int ExitInstance();

public:

afx_msg void OnEndThread(WPARAM wParam,LPARAM lParam);

protected:

int m_iThreadId;

static HHOOK m_hKeyBdHook;

static HHOOK m_hMouseHook;

static LRESULT CALLBACK KeyBdHookProc(int nCode,WPARAM wParam,LPARAM lParam);

static LRESULT CALLBACK MouseHookProc(int nCode,WPARAM wParam,LPARAM lParam);

protected:

DECLARE_MESSAGE_MAP()

};

HHOOK CHookThread::m_hKeyBdHook = NULL;

HHOOK CHookThread::m_hMouseHook = NULL;

IMPLEMENT_DYNCREATE(CHookThread, CWinThread)

CHookThread::CHookThread(int iThreadId) : m_iThreadId(iThreadId)

{

}

CHookThread::~CHookThread()

{

// Unhook the keyboard

if (m_hKeyBdHook)

{

UnhookWindowsHookEx(m_hKeyBdHook);

m_hKeyBdHook = NULL;

}

// Unhook the mouse

if (m_hMouseHook)

{

UnhookWindowsHookEx(m_hMouseHook);

m_hMouseHook = NULL;

}

}

BOOL CHookThread::InitInstance()

{

// Start recording the keyboard messages

HINSTANCE hInstance = AfxGetInstanceHandle();

m_hKeyBdHook = SetWindowsHookEx(WH_KEYBOARD,CHookThread::KeyBdHookProc,hInstance,m_iThreadId);

if (!m_hKeyBdHook)

DebugLastError();

// Start recording the mouse messages

m_hMouseHook = SetWindowsHookEx(WH_MOUSE,CHookThread::MouseHookProc,hInstance,m_iThreadId);

if (!m_hMouseHook)

DebugLastError();

return TRUE;

}

int CHookThread::ExitInstance()

{

return CWinThread::ExitInstance();

}

// CHookThread message handlers

BEGIN_MESSAGE_MAP(CHookThread, CWinThread)

ON_THREAD_MESSAGE(WM_ENDTHREAD,&CHookThread::OnEndThread)

END_MESSAGE_MAP()

// Record the keyboard messages

LRESULT CALLBACK CHookThread::KeyBdHookProc(int nCode,WPARAM wParam,LPARAM lParam)

{

LRESULT Res = CallNextHookEx(m_hKeyBdHook,nCode,wParam,lParam);

return Res;

}

// Record the mouse messages

LRESULT CALLBACK CHookThread::MouseHookProc(int nCode,WPARAM wParam,LPARAM lParam)

{

LRESULT Res = CallNextHookEx(m_hMouseHook,nCode,wParam,lParam);

return Res;

}

void CHookThread::OnEndThread(WPARAM wParam,LPARAM lParam)

{

// End the thread

PostQuitMessage(0);

}

Step 2 Code

In the constructor of the dialog or the view class, create the thread that creates the hook.  Make sure to give it the thread id of the current application!

// CRemoteDesktopView construction/destruction

Ctor::Ctor()

{

// Hook the keyboard and mouse

m_pHookThread = new CHookThread(GetCurrentThreadId());

m_pHookThread->CreateThread();

}

Ctor::~Ctor()

{

// Unhook the keyboard and mouse

m_pHookThread->PostThreadMessage(WM_ENDTHREAD,0,0);

}

This is all there is to it.  Of course you are responsible for filling in the code after the actual event is received!  In my case, I write PC remote control software and I use journaling to help me control the server by recording the messages on one machine and playing them back on another.

Monday, July 06, 2009 1:54 AM by FaubcubWerb

# greek live radio

Sunday, July 12, 2009 8:08 PM by William C

# re: Low-Level Keyboard Hook in C#

I have converted it into vb.net xpress for who ever wants it. Enjoy.

Imports System

Imports System.Diagnostics

Imports System.Windows.Forms

Imports System.Runtime.InteropServices

Public Class Form1

   Private Const WH_KEYBOARD_LL As Integer = 13

   Private Const WM_KEYDOWN As Integer = &H100

   Private Shared _proc As New LowLevelKeyboardProc(AddressOf HookCallback)

   Private Shared _hookID As IntPtr = IntPtr.Zero

   Private Shared Function SetHook(ByVal proc As LowLevelKeyboardProc) As IntPtr

       Using curProcess As Process = Process.GetCurrentProcess()

           Using curModule As ProcessModule = curProcess.MainModule

               Return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0)

           End Using

       End Using

   End Function

   Private Delegate Function LowLevelKeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

   Private Shared Function HookCallback(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

       If nCode >= 0 AndAlso wParam = CType(WM_KEYDOWN, IntPtr) Then

           Dim vkCode As Integer = Marshal.ReadInt32(lParam)

           'Console.WriteLine(CType(vkCode, Keys))

           MsgBox(CType(vkCode, Keys).ToString)

       End If

       Return CallNextHookEx(_hookID, nCode, wParam, lParam)

   End Function

   <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _

   Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As LowLevelKeyboardProc, ByVal hMod As IntPtr, ByVal dwThreadId As UInteger) As IntPtr

   End Function

   <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _

   Private Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean

   End Function

   <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _

   Private Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

   End Function

   <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _

   Private Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr

   End Function

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

       _hookID = SetHook(_proc)

       Application.Run()

       UnhookWindowsHookEx(_hookID)

   End Sub

End Class

Wednesday, July 15, 2009 5:16 AM by Nitin

# re: Low-Level Keyboard Hook in C#

Thanks for the code I found it very very useful but how can we use for disable Alt+F4 ?

I tried my best with this code it doesn't work. Actually when pressing Alt+F4 it is not even calling HookCallback function. So, there is no way to track it.

Is there anyone know any idea to get around this ?

Tuesday, July 21, 2009 8:39 AM by dvdamrketzz

# диски blu-ray фильмы по 20$ dvd фильмы диски по 1.8$

Диски blu-ray фильмы по 20$ dvd фильмы диски новинки по 1.8$

в наличии и под заказ, доставка в течении 3х дней

[url=http://www.dvd-market.com.ua]

[img]http://www.dvd-market.com.ua/products_pictures/SAW4bluray.jpg[/img][/url]

наш сайт www.dvd-market.com.ua

Wednesday, July 22, 2009 10:18 PM by TYRichard

# responsibility useful suburb

Very interesting site.  I appreciate your comment about my   black  script  Do you want a fresh joke from net?   Who was Snow White's brother? Egg White. Get the yolk?

http://zmyrel.homesta.com

Saturday, July 25, 2009 12:13 AM by fincareertut

# you be subjected to a monetary crisis?

How to build a [url=http://timezonegames.co.in/_backup/index.php]career in finance[/url]? We know as it to do!

In a turning-point the in the most suitable way of all to do a career.

We drive avoid you herein :)

On our portal you desire catch sight of the first-class suggestions on stint!

Wednesday, August 05, 2009 4:59 AM by michaeljyuti

# Funance crisis

And for you crisis?

you heard of new law, about an exit from a crisis:

agreement about [url=http://www.netvibes.com/debt_consolidation]debt consolidation[/url]

This agreement narrates about new on-line finance center, where any man, can get a credit.

Wednesday, August 12, 2009 8:25 AM by shityoucantremember

# re: Low-Level Keyboard Hook in C#

Cool post, I'll try this tonight!

Saturday, August 15, 2009 2:25 AM by ComputerAngel

# re: Low-Level Keyboard Hook in C#

Hi,

I tried your application and it works great except a little problem. May be you can help me out.

In the HookCallback function we get the keys like Keys.Oem1, Keys.A etc.. The problem is i want to convert keys.Oem1 to actual characters of the inputed keys that a "real" application sees. I have tried MapVirtualKeyW but it has limitation since it is blind to any keyboard state such as the shift key, etc. i believe WM_CHAR is the correct way to doing it but how :( dont know. i also googled but no luck.

Thanks for your help in advance

Wednesday, October 14, 2009 3:16 PM by TheRage3K

# re: Low-Level Keyboard Hook in C#

Thanks!  I had some code to capture the key press... but without the "Marshal.ReadInt32(lparam)", I didn't know WHICH key was being pressed!  This provided the missing link.

Wednesday, October 14, 2009 10:27 PM by Гносис

# re: Low-Level Keyboard Hook in C#

How to eat key strokes?

For example, i need to clear key buffer, to avoid print space, when i press WINKEY + SPACE, and perform some operation...

private static IntPtr HookCallback(

  int nCode, IntPtr wParam, IntPtr lParam)

{

 int vkCode = Marshal.ReadInt32(lParam);

 if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)

 {

   if ((Keys)vkCode == Keys.LWin ||

       (Keys)vkCode == Keys.RWin)

   {

     WinKeyStillPressed = true;

   }

 }

 if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP)

{

  if ((Keys)vkCode == Keys.LWin ||

      (Keys)vkCode == Keys.RWin)

  { //clear flag

    WinKeyStillPressed = false;

  }

  if (WinKeyStillPressed)

  {

    if ((Keys)vkCode == Keys.Space)

    {

      PlayPauseInner(); // My Styff

      return CallNextHookEx((IntPtr)0, 0, wParam, (IntPtr)0); // does not eat key strokes

      return (IntPtr)0; // does not eat key strokes

      return (IntPtr)1; // does not eat key strokes

    }

    if ((Keys)vkCode == Keys.Left)

    {

      PlayRewind(); // My Styff

    }

    if ((Keys)vkCode == Keys.Right)

    {

      PlayForward(); // My Styff

    }

  }

}

return CallNextHookEx((IntPtr)0, 0, wParam, (IntPtr)0);

}

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker