Kristian Kraljić You may compare programming with poetry,
a harmonic script is a piece of creativity which will last forever.
- Kristian Kraljić

Java – Global (low level) Keyboard / Mouse Hook

by Kristian Kraljic, February 9, 2016

About five years ago I started this blog by picking up an idea of Johannes Schüth (Jotschi) about a global keyboard and mouse listener for Java. Today I am very happy to announce the next major version of the library now available on GitHub!

system-hook-logo

Keyboard and mouse events in Java only work, if the registered component is in focus. For example, in case a window looses its focus (e.g. when minimized), it stops receiving any more events. Through a low-level system-wide hook it’s possible to deliver those events regardless. You’ll find all sources of the latest release, as well as binary bundles / prepackaged Java archives (JAR) on the GitHub project page.

The old post describes all changes I did to the initial version by Johannes (Jotschi). For the new major release I again reworked nearly every part of the library, to make it more stable and versatile. Here is what I did:

  • Optimized the native library C code, fixed bugs and removed all parts requireing a C++ compiler in the first place.
  • Renamed the event classes and listener interfaces and prepended Global to avoid conflicts with existing (Swing) event listeners.
  • Added support for mouseWheel events to the GlobalMouseListener.
  • Again allowed negative "out of bounds" values for GlobalMouseEvents, to also track the mouse pointer off screen (e.g. on multi-monitor setups).
  • Improved the threading concept and implemented a native error handling. The GlobalKeyboardHook and GlobalMouseHook constructors will now throw a UnsatisfiedLinkError if the native libraries can not be loaded or a RuntimeException in case hooking fails.
  • All the code has been moved to GitHub and binaries are now beeing continuously built by AppVeyor. Feel free to contribute on GitHub!

(Again) Last but not least, please share your ideas and problems in the comments. I will try to enhance the Global Keyboard / Mouse Hook based on your feedback. For the next release let’s see if we can get Linux and / or Mac OSX support going.

202 Comments

  1. Daniel says:

    I tried to create a basic GlobalKeyboardHook and kept getting this error and I don’t know how to fix it. could you help me?

    NATIVE: DllMain – DLL_PROCESS_ATTACH
    NATIVE: registerHook – Hook start
    NATIVE: registerHook – Hook failed with error 126: The specified module could not be found.

    Exception in thread “main” java.lang.RuntimeException: Low-level keyboard hook failed (-2)
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.(GlobalKeyboardHook.java:169)
    at lc.kra.system.keyboard.GlobalKeyboardHook$2.(GlobalKeyboardHook.java:89)
    at lc.kra.system.keyboard.GlobalKeyboardHook.(GlobalKeyboardHook.java:89)
    at MainClass.main(MainClass.java:7)

    • Hello Daniel, which operating system / JVM architecture are you wofking on? You get the debug output, so you downloaded one of the architecture specific packages from AppVeyor. Make sure you use the 32-bit DLLs / JAR, with a 32-bit JVM on a Windows 32-bit machine only. Use the 64-bit files, with a 64-bit JVM on a 64-bit operating system. Any other combination of those could cause the error you posted.

      Hope this helps. Regards, Kristian

    • Daniel says:

      I am running windows 10 64-bit with JVM JDK 1.8 and I made sure I downloaded the JAR file located in the Configuration: Debug; Platform: x64/ artifacts/target/system-hook-2.1.jar. I am referencing the file inside eclipse’s project folder. the same thing happened when I tried to export it and run it as an executable JAR file.

    • Hey Daniel. Hope we can figure this out. Just to be sure. Especially if you have multiple JVMs installed, it often happens that you execute on a 32-bit JVM, even if you are running it on a 64-bit operating system. Could you please check and run the following command on your console:

      java -version

      The last line should say something similar to:

      Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode)

    • Daniel says:

      java version “1.8.0_71”
      Java(TM) SE Runtime Environment (build 1.8.0_71-b15)
      Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)

    • Daniel says:

      for some reason, restarting my computer solved the problem.

    • Hello Daniel, glad that helped. Sorry that I had no time to figure out the problem. Please do also see the answer I have given to Mohammad on the 3rd of March 2016, always shut down your hook properly, otherwise you run out of handles quickly.

    • Pham Trung Duc says:

      Hello Kristian Kraljic, can your lib can get the kind of the system cursor (wait, arrow, hand and other)? I have problem with it, i find by a day with no result. Thank you !

    • @Pham Trung Duc, sorry that’s not possible via the library. If you find a Windows API function to do this, feel free to extend the MouseHook.c and GlobalMouseEvent.java files and re-compile the library.

    • Napoleon says:

      Hello, I used your program in a JFRAME Project. It works perfectly, when I compile. It however seems to fail when i build the actual project. Is there something wrong with the java file? Im using Netbeans.

    • Hello Napoleon, I assume by “bulding” your project, you mean to package everthing into an (executable) JAR file to have it run, right? I don’t know Netbeans, but at least in Eclipse you have to make sure, that all dependent JAR files (such as this library, including DLLs) are re-packaged into the final product. If this is not the case it’ll not work. What’s the error message when you try to execute the build product on console?

  2. John says:

    Hi. Thank you for your interested library.
    But I’m having a problem using it.
    How can I solve the Low-level keyboard hook failed?

    • Hello John, well this heavily depends on why the hooking fails. If it works for a certain amount of times and then fails, I suggest to check the answer I have given to Mohammad on the 3rd of March 2016, always shut down your hook properly, otherwise you run out of handles quickly. If this doesn’t help, please download the debug DLLs as described here, to get a extended log output.

  3. Subin says:

    Hey Kristian,
    I am getting this excepion:

    Exception in thread “Global Keyboard Hook Thread” java.lang.UnsatisfiedLinkError: lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook()I
    Global keyboard hook successfully started, press [escape] key to shutdown.
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook(Native Method)
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.run(GlobalKeyboardHook.java:174)

    • Hello Subin, which operating system are you using? Are you using the pre-bundled JAR file or do you run the .class / .java files stand-alone? Could you please go to console (cmd), execute the following two commands and paste the result here?

      systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
      java -version

  4. TT says:

    ty for ur project …. it’s work perfectly :)

  5. Rana says:

    I am getting this error too:

    Exception in thread “Global Keyboard Hook Thread” java.lang.UnsatisfiedLinkError: lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook()I
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook(Native Method)
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.run(GlobalKeyboardHook.java:174)

    • Hello Rana, same for you. Which operating system are you using? Are you using the pre-bundled JAR file or do you run the .class / .java files stand-alone? Could you please go to console (cmd), execute the following two commands and paste the result here?

      systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
      java -version

  6. Roland says:

    Hello. Will there be support for Linux in the future? If there isn’t right now (or the next 3 to 6 months) that’s okay for me, but I do need it in the future. A Java cross-platform global keylistener would be freakin’ awesome! :D

    • Hello Roland. Linux and Mac support are planned, but I didn’t find the time to implement this yet. Especially because Linux low-level keyboard / mouse hooks are quite tedious to implement. You can watch the GitHub repository to get notified on any updates! Hope this helps. :-)

    • Roland says:

      Hmm.. Yes I was afraid this might be tough stuff. Do you have any idea when (roughly) support for Linux might ready? Just so I have an idea. Could it still happen some time this year?

      Keep up the good work! :)

    • Sorry, I can’t make any promises… This year is really packed. Mostly I’m finding my “Qi” nearing the end of year. Just look at my other blog posts, they are mostly written in December. :-) Hope that’s fine anyways, I’ve been looking forward to a Linux support for a long time.

  7. Kundan Suthar says:

    I ma getting below error while running command “mvn clean install” , [please help (OS – windows 7 64 bit , jdk 1.8)

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-antrun-plugin:1.8:
    run (compile-native) on project system-hook: An Ant BuildException has occured:
    The following error occurred while executing this line:
    [ERROR] C:\Users\Remedies\Downloads\system-hook-master\system-hook-master\build.
    xml:115: Could not launch gcc: java.io.IOException: Cannot run program “gcc” (in
    directory “C:\Users\Remedies\Downloads\system-hook-master\system-hook-master\ta
    rget\objects”): CreateProcess error=2, The system cannot find the file specified

    [ERROR] around Ant part …… @ 4:8 in C:\Users\Remedies\Downloads\system-
    hook-master\system-hook-master\target\antrun\build-main.xml
    [ERROR] -> [Help 1]

    • Hello Kundan, if you’d like to build the library a C99 compatible compiler / linker bundle is required to build the native libraries, see MSYS2. In case you didn’t do any modification to the code, there is no need for building the library from scratch. You may go to the releases section on GitHub and download a pre-bundled JAR. Hope this helps.

  8. aszdf says:

    alert(“hello”);

  9. Gustavo says:

    Hi, Kristian very usefull library, congrats. Is there a way to read a keyboard event and stop the event of the key pressed? And is there a way to identify the keyboard?

    I want to use a numeric keypad for identification and the key events in that keyboard must be catch only in my application. Is there a way to do that?

    Thanks

    • Hello Gustavo, glad you like my library. To answer your questions:

      > Is there a way to read a keyboard event and stop the event of the key pressed?
      The library does not provide such a functionallity by default, same goes for Windows. But there might be a way to achieve your desired behaviour. The library uses a low-level keyboard hook. See the implementation in KeyboardHook.c. The way the low-level hooks work, is that one hook is called after another. Each hook has to call the next hook by invoking CallNextHookEx. If one hook doesn’t call CallNextHookEx, the “next” program will not get the keyboard event. Hook priorities are based on the order in which the hooks are installed. The hook installed latest, has the highest priority. This means you’ll have to ensure that the low-level hook is installed *after* your program was started. Last but not least, you’ll have to recompile the library and remove the CallNextHookEx call. It’s a fiddely solution, but I don’t think there’s another option.

      > And is there a way to identify the keyboard?
      No, not for the low-level keyboard hook in my knowledge. For this I think you have to go “even deeper” and use raw input. Unfortunately this can’t be provided by this library.

      Hope this helps. Regards, Kristian

  10. Conan says:

    on Win10, got message:-

    Exception in thread “Global Keyboard Hook Thread” java.lang.UnsatisfiedLinkError: lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook()I
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook(Native Method)
    at lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.run(GlobalKeyboardHook.java:174)
    Exception in thread “Global Mouse Hook Thread” java.lang.UnsatisfiedLinkError: lc.kra.system.mouse.GlobalMouseHook$NativeMouseHook.registerHook()I
    at lc.kra.system.mouse.GlobalMouseHook$NativeMouseHook.registerHook(Native Method)
    at lc.kra.system.mouse.GlobalMouseHook$NativeMouseHook.run(GlobalMouseHook.java:196)
    Global keyboard&mouse hook successfully started, press [escape] key to shutdown.

    • Hello Conan, which operating system are you using? Are you using the pre-bundled JAR file or do you run the .class / .java files stand-alone? Could you please go to console (cmd), execute the following two commands and paste the result here?

      systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
      java -version

  11. Max Kelly says:

    Hello,

    I am trying to learn more about security and was hoping to use your software to experiment with keyloggers. I was curious if you could help me with an error that someone else posted above. The error I am getting is as follows:

    keyboardhook-windows-amd64.dll not found in lib directory

    It occurs when I try and run the GlobalKeyboardExample. I am trying to use Maven because your JAR did not seem to work. I do not have much preference as to which I use, so long as they work.

    • Hello Max, using Maven should essentially do the same thing, as using the JAR file. If you are using the JAR file instead, are you getting the same kind of error message?

    • Max Kelly says:

      In response to your comment about whether the JAR file gives me the same error, I got it to work. There is another person on GitHub who forked your project and has all the .dll and .lib files needed. Sadly, I cannot find the link anymore. I downloaded the files from his GitHub and stuff just started working.

      That said, your program is super cool! This is really cool to see and use. I am hoping to learn a lot from it. Thank you!

    • Hello Max, sadly I coudn’t find any fork provding the files either? Generally you can find a pre-packaged JAR file (containing the DLL files) in the releases section. If you just need the DLL files, you’ll find them at Appveyor. Hope this helps. Thanks for your feedback.

  12. user202729 says:

    I also get the similar error:

    Exception in thread “Global Keyboard Hook Thread” java.lang.UnsatisfiedLinkError: lc.kra.system.keyboard.GlobalKeyboardHook$NativeKeyboardHook.registerHook()I

    {…}

    I am using the pre-packed jar as a library. I use NetBeans IDE 8.0.2, and when execute two commands I get:

    OS Name: Microsoft Windows 10 Pro
    OS Version: 10.0.14393 N/A Build 14393
    System Type: X86-based PC

    java version “1.8.0_101”
    Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
    Java HotSpot(TM) Client VM (build 25.101-b13, mixed mode)

    respectively.

    I have tried restarting my computer and it does not work.