Share via


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);
}

Comments

  • Anonymous
    May 03, 2006
    Hi Stephen,

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

    Thanks.
    Regards,

    Soumitra

  • Anonymous
    May 03, 2006
    Оказывается, это очень просто реализовать. Стивен показывает элементарный пример

  • Anonymous
    May 03, 2006
    After my last post on implementing low-level keyboard hooks in C#, Soumitra asked if it was possible...

  • Anonymous
    May 03, 2006
    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.

  • Anonymous
    May 03, 2006
    Hey

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



  • Anonymous
    May 03, 2006
    ALT is a system key and won't be handled by the hook because of the filter for WM_KEYDOWN in HookCallback.

  • Anonymous
    May 03, 2006
    I added a check for WM_SYSKEYDOWN and got the alt and altgr keys

    private const int WM_SYSKEYDOWN = 0x0104;

  • Anonymous
    May 10, 2006
    great stuff!

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

    thanx.

  • Anonymous
    May 10, 2006
    System.Windows.Forms.Control.ModifierKeys should do the trick, telling you whether shift, alt, and/or control are pressed.

  • Anonymous
    May 10, 2006
    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??

  • Anonymous
    May 11, 2006
    if (Keys.C == (Keys)vkCode && Keys.Control == Control.ModifierKeys)

  • Anonymous
    May 11, 2006
    thank you very much.

  • Anonymous
    July 10, 2006
    Thx, very good code

  • Anonymous
    August 09, 2006
    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

  • Anonymous
    August 11, 2006
    Thinks, very goo-od!

  • Anonymous
    September 10, 2006
    I have tried the code. But I only get this error

    C:Documents and SettingsThomasMy DocumentsVisual Studio ProjectsHooktestInterceptKeys.cs(10): Method 'InterceptKeys.HookCallback(int, System.IntPtr, System.IntPtr)' referenced without parentheses

    complaing on this!
    private static LowLevelKeyboardProc _proc = HookCallback;

  • Anonymous
    September 10, 2006
    You're probably using C# 1.x, rather than 2.0.  This code is C# 2.0, making use of delegate inference.

  • Anonymous
    September 17, 2006
    The comment has been removed

  • Anonymous
    September 20, 2006
    Is there a way to do the same thing in C#.NET 1.1 (as below) or is not possible?
    -----
    C:Documents and SettingsThomasMy DocumentsVisual Studio ProjectsHooktestInterceptKeys.cs(10): Method 'InterceptKeys.HookCallback(int, System.IntPtr, System.IntPtr)' referenced without parentheses

    complaing on this!
    private static LowLevelKeyboardProc _proc = HookCallback;

  • Anonymous
    September 20, 2006
    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.

  • Anonymous
    November 10, 2006
    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.

  • Anonymous
    November 15, 2006
    How can i run KeyboardHook at backgroud and trap all keys at all programs.

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

  • Anonymous
    November 17, 2006
    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.

  • Anonymous
    December 24, 2006
    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.

  • Anonymous
    January 04, 2007
    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

  • Anonymous
    January 06, 2007
    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.

  • Anonymous
    January 16, 2007
    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

  • Anonymous
    January 16, 2007
    The comment has been removed

  • Anonymous
    January 16, 2007
    The comment has been removed

  • Anonymous
    January 31, 2007
    The comment has been removed

  • Anonymous
    February 01, 2007
    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??

  • Anonymous
    February 01, 2007
    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.

  • Anonymous
    February 02, 2007
    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.

  • Anonymous
    February 09, 2007
    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); }

  • Anonymous
    February 28, 2007
    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.

  • Anonymous
    February 28, 2007
    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.

  • Anonymous
    March 01, 2007
    @Rok: you can 'return new IntPtr(1);' for the key's you want to block.

  • Anonymous
    March 02, 2007
    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.

  • Anonymous
    March 02, 2007
    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.

  • Anonymous
    March 14, 2007
    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

  • Anonymous
    March 15, 2007
    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

  • Anonymous
    March 15, 2007
    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.

  • Anonymous
    March 15, 2007
    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 ???

  • Anonymous
    March 15, 2007
    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); }

  • Anonymous
    March 15, 2007
    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).

  • Anonymous
    April 15, 2007
    hi stephen do you have anything similar for the PocketPC regards john

  • Anonymous
    April 20, 2007
    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

  • Anonymous
    April 20, 2007
    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

  • Anonymous
    April 20, 2007
    Is there a way to just intercept for current process key press?  The sample code catch all process key action, right? Thanks, joe

  • Anonymous
    April 21, 2007
    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.

  • Anonymous
    April 23, 2007
    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.

  • Anonymous
    April 23, 2007
    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."

  • Anonymous
    April 23, 2007
    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.

  • Anonymous
    April 23, 2007
    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".

  • Anonymous
    April 23, 2007
    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.

  • Anonymous
    May 05, 2007
    The comment has been removed

  • Anonymous
    May 09, 2007
    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

  • Anonymous
    May 09, 2007
    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

  • Anonymous
    May 09, 2007
    Ah right. Thanks for your help! :)

  • Dan
  • Anonymous
    May 19, 2007
    The comment has been removed

  • Anonymous
    June 04, 2007
    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.

  • Anonymous
    June 05, 2007
    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?

  • Anonymous
    June 05, 2007
    (PS I am using .NET 1.1 and have adapted the code accordingly based on your previous comments)

  • Anonymous
    June 10, 2007
    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?

  • Anonymous
    June 10, 2007
    One more thing: I'm using Vista 64-bit.

  • Anonymous
    June 15, 2007
    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?

  • Anonymous
    June 15, 2007
    Varix, just make sure to call CallNextHookEx in all places where you want the keys passed along.

  • Anonymous
    July 23, 2007
    Will this hook work with 3d games that use Directx?

  • Anonymous
    August 03, 2007
    Great code. Thank you very much.

  • Anonymous
    August 03, 2007
    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?

  • Anonymous
    August 06, 2007
    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,

  • Anonymous
    August 06, 2007
    For everyone asking about Windows services and hooks, see: http://www.experts-exchange.com/Programming/Languages/CPP/Q_21262041.html?qid=21262041 http://www.codeguru.com/forum/showthread.php?t=389394 http://www.thescripts.com/forum/thread533002.html Hope that helps, Stephen

  • Anonymous
    August 27, 2007
    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?

  • Anonymous
    September 04, 2007
    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

  • Anonymous
    September 05, 2007
    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

  • Anonymous
    September 05, 2007
    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

  • Anonymous
    September 10, 2007
    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

  • Anonymous
    September 19, 2007
    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

  • Anonymous
    September 20, 2007
    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

  • Anonymous
    October 08, 2007
    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!

  • Anonymous
    October 09, 2007
    Bob, you can use GetKeyState from user32.dll to check the status of the shift key, for example.

  • Anonymous
    October 10, 2007
    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.

  • Anonymous
    October 16, 2007
    Any solution which make this work on vista.

  • Anonymous
    October 19, 2007
    The comment has been removed

  • Anonymous
    October 23, 2007
    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.

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

  • Anonymous
    January 06, 2008
    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?

  • Anonymous
    January 06, 2008
    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?

  • Anonymous
    January 07, 2008
    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

  • Anonymous
    January 10, 2008
    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"
  • Anonymous
    January 11, 2008
    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

  • Anonymous
    January 12, 2008
    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.

  • Anonymous
    January 15, 2008
    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'?

  • Anonymous
    January 18, 2008
    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... :(

  • Anonymous
    January 20, 2008
    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.

  • Anonymous
    February 03, 2008
    Hi Stephen, Do you have anything similiar for low-level mouse hook? Thanks.

  • Anonymous
    February 04, 2008
    http://blogs.msdn.com/toub/archive/2006/05/03/589468.aspx

  • Anonymous
    February 19, 2008
    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!

  • Anonymous
    February 22, 2008
    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

  • Anonymous
    February 25, 2008
    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

  • Anonymous
    February 25, 2008
    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.

  • Anonymous
    March 06, 2008
    Hi, I want to hook Fn+ keys. For ex Fn+F1..F10. Please advise How to go about it. Thanks a lot.

  • Anonymous
    March 27, 2008
    i want hook for toggling windows

  • Anonymous
    April 08, 2008
    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

  • Anonymous
    April 22, 2008
    PingBack from http://rodgerbenham.wordpress.com/2008/04/23/low-level-keyboard-hooks-in-vbnet/

  • Anonymous
    May 07, 2008
    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?
  • Anonymous
    May 09, 2008
    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?

  • Anonymous
    May 16, 2008
    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.

  • Anonymous
    May 16, 2008
    The comment has been removed

  • Anonymous
    May 16, 2008
    I am having trouble capturing shift+{any kay}

  • Anonymous
    May 30, 2008
    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!!

  • Anonymous
    June 04, 2008
    Thank you so much this works like a dream. You dont know how much this just helped me!!!

  • Anonymous
    June 20, 2008
    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.

  • Anonymous
    June 21, 2008
    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

  • Anonymous
    June 22, 2008
    Hi! Me again... The timer works fine, there was a problem somewhere else in my code... Thanks anyway. Nicholas

  • Anonymous
    June 25, 2008
    kool application... this is what i was looking for from long time

  • Anonymous
    July 01, 2008
    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....

  • Anonymous
    July 07, 2008
    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,

  • Anonymous
    July 09, 2008
    It's very useful code. Thank you a lot.

  • Anonymous
    July 22, 2008
    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!!

  • Anonymous
    July 23, 2008
    Okey, I found the way to this. Here is the code: put it in AfterInstall: RegistryKey ckey = Registry.LocalMachine.OpenSubKey(@"SYSTEMCurrentControlSetServicesnServiceName",true);            if (ckey != null)            {                if (ckey.GetValue("Type") != null)                {                    ckey.SetValue("Type", ((int)ckey.GetValue("Type") | 272));                 }              }

  • Anonymous
    August 08, 2008
    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?

  • Anonymous
    August 19, 2008
    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.

  • Anonymous
    August 24, 2008
    4gGood idea.2f I compleatly disagree with last post .  nir <a href="http://skuper.ru">ламинат купить</a> 6r

  • Anonymous
    August 28, 2008
    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.

  • Anonymous
    September 13, 2008
    The comment has been removed

  • Anonymous
    September 29, 2008
    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

  • Anonymous
    October 20, 2008
    Hi, have you ever tried to use comments in your code? I think they are fundamental.

  • Anonymous
    October 24, 2008
    原文:http://www.codeproject.com/KB/system/CSLLKeyboard.aspx

  • Anonymous
    November 09, 2008
    How would I use this in a Windows Form Application?

  • Anonymous
    November 13, 2008
    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?

  • Anonymous
    November 16, 2008
    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.

  • Anonymous
    January 18, 2009
    PingBack from http://www.keyongtech.com/1193393-keypress-in-word

  • Anonymous
    January 21, 2009
    PingBack from http://www.hilpers.it/2654433-shortcut-key-globale

  • Anonymous
    February 05, 2009
    PingBack from http://www.axino.net/tutorial/2009/02/keylogger-in-c-introduction

  • Anonymous
    February 06, 2009
    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...??

  • Anonymous
    February 07, 2009
    The comment has been removed

  • Anonymous
    February 10, 2009
    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?

  • Anonymous
    February 18, 2009
    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

  • Anonymous
    February 19, 2009
    Thank you very much for your code. 3 years later still helping peoples.

  • Anonymous
    February 21, 2009
    thanx for the interesting posts

  • Anonymous
    February 23, 2009
    awesome piece of code. Cheers!

  • Anonymous
    March 03, 2009
    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.

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

  • Anonymous
    April 06, 2009
    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?

  • Anonymous
    May 06, 2009
    Great Post Dear I was looking exactly the same thing you did. Thanks. Keep it up.

  • Anonymous
    June 09, 2009
    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

  • Anonymous
    June 12, 2009
    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

  • Anonymous
    June 24, 2009
    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

  • Anonymous
    June 25, 2009
    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.

  • Anonymous
    July 05, 2009
    [url=http://www.mygreek.fm/][img]http://img7.imageshost.ru/imgs/090701/7125a107e6/5380c.png[/img][/url] [b][url=http://www.mygreek.fm/]music from greek [/url][/b]

  • Anonymous
    July 12, 2009
    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

  • Anonymous
    July 14, 2009
    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 ?

  • Anonymous
    July 21, 2009
    Диски 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

  • Anonymous
    July 22, 2009
    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

  • Anonymous
    July 24, 2009
    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!

  • Anonymous
    August 04, 2009
    The comment has been removed

  • Anonymous
    August 12, 2009
    Cool post, I'll try this tonight!

  • Anonymous
    August 14, 2009
    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

  • Anonymous
    October 14, 2009
    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.

  • Anonymous
    October 14, 2009
    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); }

  • Anonymous
    November 29, 2009
    hi all,     how to find the name of all the processes receiving key board input.please help me on this... Thanks in advance

  • Anonymous
    December 14, 2009
    Hi, Ist id possible to trapp series of keystorkes  before pressing enter key?

  • Anonymous
    December 14, 2009
    I want to trap series of keystrokes i.e "a1de" How is it possible?

  • Anonymous
    January 06, 2010
    The comment has been removed

  • Anonymous
    January 13, 2010
    I'm trying to use this code to output a different keyboard char than the one actually typed. The relevant message has been changed to this:    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)    {        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)        {            //Console.WriteLine((Keys)vkCode);            KBDLLHOOKSTRUCT replacementKey = new KBDLLHOOKSTRUCT();            Marshal.PtrToStructure(lParam, replacementKey);            replacementKey.vkCode = 90; // char 'Z'            Marshal.StructureToPtr(replacementKey, lParam, true);        }        return CallNextHookEx(_hookID, nCode, wParam, lParam);    } Unfortunately this outputs a "A first chance exception of type 'System.ArgumentException' occurred in foobar.exe" every time I press a key. Any idea?

  • Anonymous
    January 22, 2010
    The comment has been removed

  • Anonymous
    March 08, 2010
    Nurem >> try this: http://www.pinvoke.net/default.aspx/user32/RegisterHotKey.html

  • Anonymous
    June 15, 2010
    Cool, Do you know how to do the (approx.) equivilant in Visual Basic?

  • Anonymous
    June 28, 2010
    Thanks for sharing this, I remembered the days of C++ and windows programming.

  • Anonymous
    July 06, 2010
    I am new to windows programing, and i am trying to trap the ALT+TAB, ALT+ESC.. keys and then disable there action, can you help me to get this done. I need to do it in VB.Net

  • Anonymous
    August 29, 2010
    I use this sample code in windows 7; and i replace Console.WriteLine((Keys)vkCode) by  MessageBox.Show(Convert.ToString((Keys)vkCode)). when it runs, i press one key for 11 times, the hook keyboard is crashed!!!! I don't know why, can you help me plz??????

  • Anonymous
    November 06, 2010
    This is so helpful! Thanks for sharing.

  • Anonymous
    November 28, 2010
    Hi, Thanks for the above mentioned code. I was actually searching for something that can hook the keyboard events only for one application i.e. powerpoint 2007. In your code SetWindowsHookEx expects the parameter 0, therefore the hook is applied for all the applications. I do not want that. i only want the hook to be applicable with powerpoint 2007 application. Can you help?

  • Anonymous
    December 17, 2010
    Thanks for the piece of code it's extremely helpful!  :)

  • Anonymous
    December 24, 2010
    HookCallback() is never called in .NET 4.0 on XP SP3. Am I missing something?

  • Anonymous
    January 28, 2011
    I know it isn't really a productive comment, but thanks a lot for this!

  • Anonymous
    February 03, 2011
    Hello, I wanted to see if it is possible to "modify"  the hook so that it changes de key pressed, for example:  if i press "a", it will display a "b"...    

  • Anonymous
    February 08, 2011
    I would like to know what happens if I don't use the        Application.Run();  , it seems that this call is necessary to make it run. But I can't compile using   Application.Run() .   If I code a windows service how the code should be changed? Thanks

  • Anonymous
    February 09, 2011
    The comment has been removed

  • Anonymous
    February 18, 2011
    Does any1 know if I can store this KeyboardHook code in seperate Class or Module ? I dont want to mix all this KeyboardHook  with other ode in my form so I would like to have it in external module or class file? I belive this is simple, but I am not so familiar with it ..

  • Anonymous
    February 20, 2011
    how can i use the same for compact framework??

  • Anonymous
    June 09, 2011
    hi Stephen, nice article!!! how can i perform this.. ex: first press A and then B after that AB becomes C..? (deleting both A and B) press A -> A press B -> C (generally this is AB) cheers

  • Anonymous
    June 15, 2011
    my problem is that whe using low level key board hook in a console app, it can get the key information when the app lost focus which is expected, but when I change this code a little bit and make it works in a win form app, it can only get the key information just when the window get focus, but when it lost focus, it cannot get the key information anymore.

  • Anonymous
    November 16, 2011
    I am trying to run this application as task (on Task Scheduler) on Windows 7 but there is an issue which I couldn't figure out. It might be because of either threading or security? Has anyone run this code as a task or it is not possible?

  • Anonymous
    December 05, 2011
    Snow still underground rustling, more bitter cold air. When we looked around, neusoft wan to already became a XueSu ice sculpture of the world. Nomura HuangZhong, cold Lin haystack was draped thick.<a href="www.downjacketclearance.com/moncler-c-2.html">women down jacket</a>

  • Anonymous
    January 26, 2012
    Thanks for this code.

  • Anonymous
    February 08, 2012
    Thanks, made my tool complete. :)

  • Anonymous
    February 08, 2012
    Hi Is there a way to know which device send the input? i need to identify the input source because i want to filter the barcode scanner

  • Anonymous
    February 16, 2012
    Hi, Does this work for WinForm? I've tried it in winform and it's not working. If I comment out the Application.Start(); The winform will no capture the keys. If I leave Application.Start(); then the form will not show but the key capture fires. Is console app codes different than winform code? What am I missing? Thanks, ED

  • Anonymous
    February 19, 2012
    Error 1 The name 'SetHook' does not exist in the current context c:users****documentsvisual studio 2010ProjectstrycatchtrycatchProgram.cs 29 23 trycatch wat to do?

  • Anonymous
    March 10, 2012
    Hi there, I'm developing an application which is doing some things in a loop, and this loop have to breaked when any key is entered. I tried the above code but the HookCallback method is called only after the loop. Is there a way i can do any modify in this code to make it work for me ? I looked into it : www.codeproject.com/.../Processing-Global-Mouse-and-Keyboard-Hooks-in-C but it uses a lot of its own classes which is not good. VisualStudio 2010, C#, windows7, .NET 3.5

  • Anonymous
    March 21, 2012
    The comment has been removed

  • Anonymous
    April 22, 2012
    The comment has been removed

  • Anonymous
    May 18, 2012
    That was great thanks

  • Anonymous
    August 10, 2012
    Im not sure if this will get answered? but im going to ask in any case. Is there a way that we can measure the speed of the current users usage in terms of keyboard mouse activity? not using a prescribed piece of text, like most typing-tutors do, but more along the lines of how fast is the user using the keyboard and mouse independently and in combination? regardless of what the user is actually doing.

  • Anonymous
    December 10, 2012
    I have used this code in windows service, But it is not detecting any key events. Do you have any idea to handle this in windows service.

  • Anonymous
    December 31, 2012
    Hi. I'm making stopwatch using the shortcuts and it works when I press 2 times "Home" after opening the program. When I press one time or wait a little after running the program, it will start the stopwatch and nothing else. My code is as follows: private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) {            vkCode = Marshal.ReadInt32(lParam);            if ((Keys)vkCode == Keys.Home)            {                stopwatch.Reset();                stopwatch.Start();                broken = 0;                start = DateTime.Now;                while(broken == 0) {                    elapsed = stopwatch.Elapsed;                    minutes = (int)elapsed.TotalMinutes;                    fsec = 60 * (elapsed.TotalMinutes - minutes); //double                    sec = (int)fsec;                    tsOut = String.Format("{0}:{1:D2}", minutes, sec);                    Console.Write("r{0}", tsOut);                    start = DateTime.Now;                        while (start.AddSeconds(1) >= DateTime.Now) //it runs for a second                        {                            CallNextHookEx(_hookID, nCode, wParam, lParam);                            vkCode = Marshal.ReadInt32(lParam);                            if ((Keys)vkCode == Keys.End)                                broken = 1;                        }                }                stopwatch.Reset();                CallNextHookEx(_hookID, nCode, wParam, lParam);            }            if ((Keys)vkCode == Keys.End)            {                stopwatch.Reset();            }        }        return CallNextHookEx(_hookID, nCode, wParam, lParam);    } Would you help me with this?

  • Anonymous
    January 18, 2013
    can you gave the sample program sir of Low-Level Keyboard hook it gonna help me a lot in my study just send me please.. g.jhonmichael@gmail.com thanks you sir....:D

  • Anonymous
    March 09, 2013
    Hi, with this code how can I hook an USB barcode reader knowing its HID?. Regard. Lenny

  • Anonymous
    March 20, 2013
    having same prob as you reg. ll keyb proc on excel2013, saw your posting on the guy with word2013 prob's, you asked for some help, did you get any answer? my mail is permortenjensen@hotmail.com

  • Anonymous
    July 18, 2013
    I need one help. i am running application in minized mode and override wndproce() method to capture all windows message.now problem start i do not get windows message when i double click on same application. can u help to figure out it.

  • Anonymous
    October 07, 2013
    The comment has been removed

  • Anonymous
    May 20, 2014
    Why I fail to read the barcodes that created by this barcode solution(www.barcodelib.com/csharp)? Is this the barcode quiet zone setting issue?

  • Anonymous
    June 02, 2014
    barcode scanner sdk for c#.net www.keepdynamic.com/.../csharp-barcode-reader.shtml

  • Anonymous
    September 16, 2014
    i have a tool where in i will have to lock the computer if the computer is left idle for 10min while the tool is still running. Please help asap... Thanks in advance!

  • Anonymous
    September 25, 2014
    Can anyone help ? how to host wcf service in windows service which does keystroke logged and saves it to a file.

  • Anonymous
    November 03, 2014
    Thank u very much Steph, u're an angel and u'll change the world!!!

  • Anonymous
    March 11, 2015
    ttomsen, thank u so much ^_^ you helped me to run it in windows form application :) it works ;)

  • Anonymous
    March 19, 2015
    thanks for sharing this valuable code...

  • Anonymous
    September 25, 2015
    Canany one help me with hooking DOUBLE tap

  • Anonymous
    December 17, 2015
    Hello! How I can it ? switch ((Keys)vkCode) { case (Keys.C == (Keys)vkCode && Keys.Control == Control.ModifierKeys): Console.WriteLine("CTRL+C: {0}",(Keys)vkCode); break; case (Keys.V == (Keys)vkCode && Keys.Control == Control.ModifierKeys): Console.WriteLine("CTRL+V: {0}",(Keys)vkCode); break; etc

  • Anonymous
    February 23, 2016
    I am using the mute key to switch the keyboard to a different language. Is it possible to make the mute key do only this thing without disabling the sound? Thanks.