Click here to Skip to main content
15,860,844 members
Articles / Programming Languages / C++

Mouse and KeyBoard Hooking utility with VC++

Rate me:
Please Sign up or sign in to vote.
4.93/5 (38 votes)
21 Mar 2010CPL4 min read 181K   27K   146   39
Test Automation software's code revealed with the help of mouse and keyboard hooking!!!

Introduction

A good white box testing is essential for the success of software. Testing is usually done with human interaction, which is both slow and expensive. Testing is a long process which needs a lot patience and keen observation. If it is a white box testing, then we need to follow some steps and run a lot of scenarios whenever we make a small change in our software’s code. Usually, the same steps are done by testers repeatedly. To overcome this problem, a lot of Test Automation tools are available in the market. Some of the famous GUI testing tools are IBM Rational Functional Tester from IBM and Phantom Automation Language from Microsoft.

This article is concentrated mainly on creating a miniature of a Test Automation tool, with the help of mouse and keyboard hooking. Keyboard and mouse hooking is no longer an undocumented activity. It is available in plenty on the internet. As we know, whenever a good technology is introduced, it has pros and cons. If we record the mouse and keyboard events without the knowledge of a user, then it is Trojan horse, key logger or a virus. But if it is done purposefully, then it is automation. The next few sections mentioned below will be fully concentrated on creating a Test Automation miniature with the help of global mouse and keyboard hooking. So hooking is a simple activity by which, we will be able to get the keyboard and mouse events in our application. Let us go in detail.

Background

Hooking of keyboard and mouse can be usually done in two ways:

  1. Thread wise Hooking

    As the name reveals, it is only limited to a thread in a process. This can be useful in our software. So hook procedure can be placed either on an EXE or a DLL. 

  2. Global Hooking

    Global Hooking is a system wide hooking. The entire keyboard or mouse event is diverted to our hook procedure. The hooking function must be placed on a separate DLL in this case.

We achieve the mouse and keyboard hooking with he help of the Windows provided SetWindowHookEx WINAPI (Hooks many types of events ). To unhook the event, we need to give UnhookWindowsHookEx WINAPI.

To demonstrate the usage of hooking, I came up with an application RecordPlayer.exe. So let me introduce the application to you. It mainly consists of three components.

  • RecordPlayer.exe
    • The application that manages the keyboard and mouse hook events from the corresponding DLL.The playback operation of the recorded steps.
  • KeyBoardHook.dll
    • Hooking the keyboard events
  • HookDll.dll
    • Hooking the mouse events

Our application consists of two operations, recording and playback. Recording is done with the help of DLLs and playback is done with the help of two APIs mainly - keybd_event and mouse_event. Now let us go under the hood. I will demonstrate the hooking activity with the help of keyboard hooking.

Using the Code

To start the keyboard hooking, firstly make a WIN32 DLL. Let us start with the header file of DLL.

Then Export the functions from the DLL, so that it can be accessible from our native application that is going to get the data from the hook procedure.

The code inside KeyBoardHookLib.h:

C++
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define LIBSPEC __declspec(dllexport)
// Our install Hook procedure.
 LIBSPEC BOOL InstallKeyBoardHook(HWND hWndParent);
// Our uninstall hook procedure.
LIBSPEC BOOL UnInstallKeyBoardHook(HWND hWndParent);
#undef LIBSPEC

The named events that registers to send the window message to RecordPlayer.exe.

C++
#define UWM_KEYBOARD_MSG ("UWM_KEYBOARD_USER_MSG")

Let us become familiar with KeyBoardHookLib.cpp.

The below steps are done to share the HANDLE mentioned inside that #pragma to be shared among DLL or to the native application from this DLL.

C++
#pragma data_seg(".SHARE")

UINT UWN_KEYSTROKE;
HWND hWndServer = NULL;
#pragma data_seg()

#pragma comment(linker,
"/section:.SHARE,rws")

The below mentioned step is done to register the window message so that we can send the keyboard events received inside the Hook function to the native executable.

C++
UWN_KEYSTROKE= ::RegisterWindowMessage(UWM_KEYBOARD_MSG);

The below mentioned static function is a keyboard procedure which receives the global keyboard events.

C++
static LRESULT CALLBACK KeyBoardMsgProc( int nCode, WPARAM wParam, LPARAM lParam)

We start the hooking of the keyboard events once InstallKeyBoardHook is called from the parent executable.

In the SetWindowHookEx, we have specified the first parameter as WH_KEYBOARD to hook the keyboard event.

C++
hook= SetWindowsHookEx( WH_KEYBOARD, (HOOKPROC)KeyBoardMsgProc, hInst, 0);

The CallNextHookEx is a optional procedure but it is highly recommented by Microsoft. If it is not called, there is a chance that other processes that have installed hook may not get the events correctly.

C++
CallNextHookEx(hook, nCode, wParam,lParam);

To uninstall the hook procedure, we need to call the UnhookWindowsHookEx specifying the Handle of returned by SetWindowHookEx.

C++
BOOL unhooked = UnhookWindowsHookEx(hook);

Points of Interest

This tool is a miniature implementation to the test automation software. But I am sure, it will give you an idea about mouse and keyboard hooking. SetWindowsHookEx can be used to inject a DLL into another process. In this article, we are dealing with WH_KEYBOARD which monitors keystroke message. The keyboard input can come from the local keyboard driver or from calls to the keybd_event function. If the input comes from a call to keybd_event, the input is "injected". WH_KEYBOARD_LL hook is not injected into another process, so it’s better. WH_SHELL can be used to get notification of the shell events. SetWindowHookEx is a very useful API, but for a good work we have to pay, so let's do so. Hooks tend to slow down the system because they increase the amount of processing the system must perform for each message. So use judiciously. If my Allah allows me, I will write more articles.

History

  • Version 1.0

License

This article, along with any associated source code and files, is licensed under The Common Public License Version 1.0 (CPL)


Written By
Software Developer (Senior) Philips HealthCare
India India
I am always looking for new technical challenges.
If you face it, contact me, I will solve it.

Comments and Discussions

 
GeneralRe: Use Newer Tool Pin
J Eakin1-Feb-12 6:29
J Eakin1-Feb-12 6:29 
QuestionI have a question... Pin
mesiasrojo11-Aug-11 0:27
mesiasrojo11-Aug-11 0:27 
AnswerRe: I have a question... Pin
Adam Roderick J17-Nov-11 23:11
Adam Roderick J17-Nov-11 23:11 
GeneralProblem with item selection in list box... Pin
chethan_mys16-Jun-10 3:57
chethan_mys16-Jun-10 3:57 
GeneralProblem with mouse wheel Pin
Tony Abraham22-Apr-10 1:56
Tony Abraham22-Apr-10 1:56 
GeneralRe: Problem with mouse wheel Pin
Adam Roderick J23-Apr-10 17:06
Adam Roderick J23-Apr-10 17:06 
GeneralReally Good Pin
Emre Guldogan24-Mar-10 0:25
Emre Guldogan24-Mar-10 0:25 
GeneralRe: Really Good Pin
Adam Roderick J24-Mar-10 18:16
Adam Roderick J24-Mar-10 18:16 
Let me check that.
Mostly it may be some sort of delay issue Smile | :)
Величие не Бога может быть недооценена.

Generalgood work Pin
cute_friend707722-Mar-10 18:59
cute_friend707722-Mar-10 18:59 
GeneralRe: good work Pin
Adam Roderick J23-Mar-10 5:37
Adam Roderick J23-Mar-10 5:37 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.