As you know: C# is a companion language to the .NET Framework platform, and it is not possible to implement global hooks with its own libraries and compiler provisions. But in practice calls to unmanaged code hold true in C#, using the DllImport property to reference methods in the unmanaged code library. Hook functions exist in user32.dll, and the function prototype is as follows:
HHOOK WINAPI SetWindowsHookEx(
__in int idHook,
__in HOOKPROC lpfn,
__in HINSTANCE hMod,
__in DWORD dwThreadId);
It can be used to register a specific type of message interception processing method with the operating system (Windows), for example, we can register a hook to block global keyboard messages, so that all keyboard press and lift events can be perceived and processed by us (it is not ruled out that there is a front-end hook to drop the message).
We can reference this function in C# by declaring it like this:
[DllImport("user32.dll")] public static extern int SetWindowsHookEx( HookType idHook, HookProc lpfn, IntPtr hInstance, int threadId );
It is worth mentioning that the HookType and HookProc above are my custom types, which is not important (because the program passes a memory address when running), but it must meet certain specifications.
The parameters of the function from top to bottom are:
idHook type, which is represented here by a shaped enum lpfn callback function when hooks come into play hInstance module handle of the application instance (usually the module handle of the application instance where your hook callback function is located) threadIdThe identifier of the thread associated with the installed hook subroutine
There are several types of hooks:
We generally use 13 to block keyboard messages and 14 to block mouse messages.
The declaration of the callback function We need to use delegates in C#, and the declaration is as follows: public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
The top-down parameter means that the parameter passed back by the nCode hook chain, 0 means that this message (by the previous message hook) is discarded, and non-0 means that this message continues to be valid
wParam message parameters
lParam message parameter
It is worth mentioning that wParam and lParam are different types of different message types, but the types of wParam can be roughly represented by the following enumeration:
lParam is generally encapsulated as a structure, which varies depending on the type of message, the following two structures are the lParam structure of mouse and keyboard messages:
When we understand the above information, we have a basic understanding of the C# implementation of hook functions, and then pay attention to a few questions:
1. Hooks take up a lot of resources, and should be canceled in time when not in use, which requires the use of the UnhookWindowsHookEx function
2. In courtesy, the hook should return the processing result of the next hook, not the processing result of the current hook alone (use CallNextHookEx to call the next hook, since the hook is set first and then take effect, so it should be done to ensure the normal delivery of the hook chain).
3. The hInstance in the hook function parameter is only where the callback function of the current hook is, and the correct address must be given
4. Because the delegate is used, it should be ensured that the memory address of the delegate (reference to the method) will not be garbaged, otherwise there will be an exception when the hook is executed
You can download the sample program I wrote, but my program needs the following main points:
1. I blocked the implementation of hooks, and only opened up the message interception and processing of keyboard and mouse (the usage method is the same as C#'s WinForm mouse and keyboard events), and you can open up others
2. I designed the hook to be in singleton mode, you can cancel it
3. Due to certain intrusion into the operating system, antivirus software may be reported as risky
4. The code is badly written, just make do with it......
Finally, the difference between programming technology and language is that their compilers and their users are different, people who use C cannot be said to be higher than those who use Java, and technology is not necessarily reflected in pointers, matrices, data structures, as long as people who understand computer principles, compilation principles, operating system principles, etc. Of course, it is good that everyone has their own favorite language and usual programming methods.
|