HookProc param - null - c#

I've made a mouse low level hook and it works fine except one problem: the procedure's param.
here's my code: http://pastebin.com/X2198UTb
My HookProc located in the middle of the code under my comment.
Is it a problem or it should be like that? if it should be like that - how can I know which window should get the right click? /// I added a condition to activate the event - right click.

Your code is quite confusing because of the fact that you declared the WH_MOUSE constant to have the value 14. WH_MOUSE actually has the value 7, and 14 is the value of WH_MOUSE_LL (and yes I know you wrote "low level" in your question).
But then you go on by using the WH_MOUSE related types. Specifically, the hook procedure of a WH_MOUSE_LL hook receives a MSLLHOOKSTRUCT structure, not the MOUSEHOOKSTRUCT you're using.
Also, as Hans and Tergiver has hinted, you should pass in the module handle of your own code, not User32.dll. Try using Marshal.GetHINSTANCE(typeof(globalMouse).Module).

This shouldn't even work at all. If you try the same thing (using LoadLibrary("User32") and a thread id of 0) in a pure native app, it will only work for a short while.
Use of a global hook requires a native (no C#) DLL. This is far more complicated than it might seem, especially if you want it to work on 64-bit Windows where you need both a 32- and 64-bit injection DLL as well as 32- and 64-bit injection processes.

Related

Why use LoadLibrary instead of just getting BaseAddress of your program

subjective...HA
ok so i've been looking around the internetz for a reasonable solution to trapping multiple keystrokes and came accross a few solutions that use the same thing (keyboard hook). One soltuion used a native call to get the IntPtr of a process by name, and the other used LoadLibrary("User32.dll")
so i figured I would be "smart" and did this (with success)
IntPtr hInstance = Process.GetCurrentProcess().MainModule.BaseAddress;
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);
as apposed to using this
IntPtr hInstance = LoadLibrary("User32.dll");
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);
is one safer than the other? am I making a fatal error that isn't showing it's head?
SetWindowsHookEx() requires a valid module handle. It uses it to figure out what DLL needs to be injected into other processes to make the hook work.
But that's only a requirement for global hooks. The two low-level hooks (WH_MOUSE_LL and WM_KEYBOARD_LL) are special, they don't require DLL injection. Windows calls the hook callback in your own process only. The sole requirement is that your thread pumps a message loop so that Windows can make the callback. Application.Run() is required.
Also the reason that you can make low-level hooks work in C#, the DLL used by global hooks cannot be written in a managed language because the injected process will not have the CLR loaded.
The quirk is that SetWindowsHookEx() checks if you passed a valid module handle but then doesn't actually use it for the low-level hooks. So any valid handle you pass will work. This quirk was fixed in Windows 7 SP1 btw, it no longer performs that check.
EDIT: My original answer left the IntPtr.Zero option open, and gave the neccesary information to help you decide. I'm adding another quote from the docs, which discusses when not to use null:
An error may occur if the hMod parameter is NULL and the dwThreadId
parameter is zero or specifies the identifier of a thread created by
another process.
Since you're using 0 as the thread id (which means "all existing threads running in the same desktop as the calling thread", as per the docs), you should NOT be using null but Marshal.GetHINSTANCE instead.
I think you should be passing either IntPtr.Zero or Marshal.GetHINSTANCE(your current module)
According to these docs, the third argument (hMod) is -
A handle to the DLL containing the hook procedure pointed to by the
lpfn parameter. The hMod parameter must be set to NULL if the
dwThreadId parameter specifies a thread created by the current process
and if the hook procedure is within the code associated with the
current process.
Also as mentioned in this article ("Windows Hooks in the .NET Framework"),
The third argument should be the HINSTANCE handle of the DLL that contains the code for the filter function. Typically, this value is set to NULL for local hooks. Do not use the .NET null object, though; use the IntPtr.Zero expression, which is the correct counterpart for Win32 null handles. The HINSTANCE argument cannot be null for systemwide hooks, but must relate to the module that contains the hook code—typically an assembly. The Marshal.GetHINSTANCE static method will return the HINSTANCE for the specified .NET module.
Also, see this question.

SetWindowsHookEx global keyboard hook not catching all keypresses

I'm writing code that is part of an automation system. I wanted to add a keyboard hook to end the test prematurely, and I did this by using SetWindowHookEx.
My code looks pretty much like this: http://support.microsoft.com/kb/318804
Here's my SetWindowsHookEx call:
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
Now, when I run my automation, keypresses from within the automation system (from SendKeys) trigger the keyboard hook method, but when I hit the keyboard manually it isn't triggered.
I can share more code if that helps, but it's part of a much larger system. I'm pretty sure that either:
My SetWindowsHookEx isn't correct, or
Something in the automation system is bypassing my keyboard hook (I don't really know how to tell though).
I've written a test application that uses the sample code from microsoft.com to determine that my approach has merit (i.e., it works), but I'm having trouble integrating it with the automation system.
Any thoughts on how to determine where things are going wrong would be greatly appreciated.
Edit: There are no other instances of SetWindowsHookEx in the automation harness. I'm not too clear the nuances of global keyboard hooks w.r.t. threads and the desktop. If I add a global keyboard hook, should it matter from where it was added?
George Mamaladze's article Processing Global Mouse and Keyboard Hooks in C# which works if the application is "in the background" on CodeProject has been around since 2004, been through multiple revisions, and he's still supporting it and updating it : as I understand it, he started his project because he could not implement global hooks in .NET, that worked when the app was running in the background, but later discovered you could hook certain "lower level" events : formerly Q318804 : now MSDN article revised (?) that says you can hook WH_KEYBOARD_LL.
Perhaps, since George's code has been field-tested by so many C# programmers, over so many years, and extensively revised against bugs or problems : there's some possible value in his code for you ? In his article, in the Version 1 "FAQ" he shows code that will make the hook application specific, rather than global.
The MSDN article cited above mentions ... in the context of the allowed hooking of low level events, as you are doing :
"Low-level hook procedures are called
on the thread that installed the hook.
Low-level hooks do not require that
the hook procedure be implemented in a
DLL."
Hypothesis : could threading be related to what you are observing ?
I'm assuming you've already been through and considered all the details on : MSDN : LowLevelKeyboardProc Function
Responding to your comment -
If you just need to test whether a key is down in order to exit your test, you could just poll on GetAsyncKeyState(), this will tell you if a particular key is down regardless of who currently has keyboard focus.
You user would have to hold a key or set of keys down long enough for your polling to notice, which means either they hold it down for a few seconds, or you have to poll more frequently than a second.
But that would be a lot less intrusive than a global keyboard hook.
Global hooks supposedly serialize parts of the kernel that normally would be async from each other, so they also harm system performance.

What does GetModuleHandle() do in this code?

Edited........
sorry Sir I was referring this piece of code from Stephen Toub's article..
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);
}
}
Can some one explain this to me in short...??
In short this code initializes a key logger. The passed in parmeter, proc, is a callback function that will be called on every key press.
The using statement just ensures immediate calls to dispose() on the declared variables (curProcess and curModule) when they leave scope, thus properly releasing resources in a expedient manner rather than waiting for the garbage collector to release them which may take a while.
SetWindowsHookEx is a win32 api call that allows you to register a callback to be called when a specific OS level event occurs. In this case the first parameter, WH_KEYBOARD_LL, specifies that you would like to register for low level keyboard events. The second parameter is the callback (a Delegate in .Net) that will be called. The third parameter is a windows handle (a pointer managed by the OS) to the module where the callback is located, in this case the main .exe for the process. Note that a process has multiple modules (exe's or dll's) loaded at any given time. The last parameter is the thread id that you would like to monitor; because 0 is passed in, the callback will be called for any key events for any window opened on the OS.
More info here about SetWindowsHookEx
GetModuleHandle() is a Windows API which in simple word returns you the handle of the loaded DLL or EXE.
You can see the detailed description of this API at this link
Straight From MSDN:
The GetModuleHandle function returns a handle to a mapped module without incrementing its reference count. Therefore, use care when passing the handle to the FreeLibrary function, because doing so can cause a DLL module to be unmapped prematurely.
This function must be used carefully in a multithreaded application. There is no guarantee that the module handle remains valid between the time this function returns the handle and the time it is used. For example, a thread retrieves a module handle, but before it uses the handle, a second thread frees the module. If the system loads another module, it could reuse the module handle that was recently freed. Therefore, first thread would have a handle to a module different than the one intended.
First as a general point for questions on Windows library functions, you should consider searching MSDN. Here is the MSDN page for GetModuleHandle(), it contains much of the relevant information.
To your question (and anyone more familiar with the Windows API feel free to correct me), a "module" is a sort of catch-all term for a program in Windows, usually specifically referring to either an executable(.exe) or a library(.dll). A "handle" is a term referring to a pointer. GetModuleHandle() returns a pointer (handle) to the specific program (module). As Pavel commented, both are very broad terms.
As for the code snippet you posted:
It's getting the current running process, as well as the current module (obvious.)
It is then calling SetWindowsHookEx (refer to the MSDN for more information) which takes in the event to hook (In this case, low level Keyboard events.), a procedure to call (proc) when the hooked event happens, and a pointer to the current program.
Refer to Hooks on the MSDN for more information on hooking.
Essentially the message of this post is make more use of the MSDN, it's a pretty solid piece of documentation :)

Respond to keyboard when not in focus? (C#, Vista)

I'm trying to write an application that responds whenever the Shift key is pressed, no matter what application currently has focus.
I tried this with SetWindowsHookEx() and with GetKeyboardState(), but both of these only work when the application's window has focus. I need it to work globally.
How do I do this?
None of the provided answers helped me solve my problem, but I found the answer myself. Here it is.
Using SetWindowsHookEx() with WH_KEYBOARD_LL was the correct approach. However, the other parameters to SetWindowsHookEx() are unintuitive:
The last parameter, dwThreadId, needs to be 0.
The second-last parameter, hMod, needs to point to some DLL. I used
User32, which is a DLL that is always loaded anyway and is used by all
processes with a GUI. I got this idea from a CodeProject post about this.
Thus, the code looks a bit like this:
instance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookFunction, instance, 0);
The documentation is unclear about the second-last parameter. It says:
The hMod parameter must be set to NULL [...] if the hook procedure is within the code associated with the current process.
It doesn't state that this only applies to some types of hooks, but not to WH_KEYBOARD_LL and WH_MOUSE_LL.
You'll have to use SetWindowsHookEx(). There are only two types of hooks that you can implement in a managed language, WH_KEYBOARD_LL and WH_MOUSE_LL. All other hooks require a DLL that can be injected into another process. Managed DLLs cannot be injected, the CLR cannot be initialized.
This blog post has a functional example.
If you use the technique in the post referenced by nobugz, you will need to make sure the delegate doesn't get garbage-collected, e.g. by using GC.KeepAlive(_proc) when setting the hook, otherwise after an indeterminate period the hook will stop working when the delagate gets GCed.
Setup a CBT hook look here http://www.codeproject.com/KB/DLL/keyboardhook.aspx

Find the Current Windows Application

I'm trying to write what I hope is a simple application tracker. That is, whenever a new application starts, or a running application becomes current, I want to note the event and start timing it's time "on top".
I have code that lists all the current applications that are running, and some code that tells me the top window (always my test console app, naturally).
What I think I'm missing is the Windows event stream to monitor or something.
I'm using .NET (C# preferred).
Any hints, tips or cheats available?
Thanks - Jonathan
I think the best way to do this would be using windows "hooks" (i.e. SetWindowsHookEx). These allow you to hook in to windows core functionality, specifically there is one called WH_CALLWNDPROC which calls a user function any time any window in the system receives a message.
You could use this to globally listen for messages that bring a window to the foreground, and/or messages for user interaction (mouse, keyboard).
However, this is a raw Windows API function primarily meant for use in a C/C++ windows DLL. You can implement it in C#, but that is a can of worms you may not want to open. But opening it would probably be the best way of doing what you're asking.
I'm not sure if there's a way to hook a Windows event, but simply polling System.Diagnostics.Process.GetProcesses() at regular intervals (say, 100ms) and looking for new/removed processes (comparing by process ID) should do the job. Also, Process.StartTime will give you the time at which the process began.
Caveat: This method may be require a higher amount of processing compare an event-based method (none of which I am aware). Processes that start and end between each poll will not be observed, but this ought to be quite rare indeed for a reasonably high polling frequency (and perhaps you do not even care about these processes anyway). Saying this, these are minor detractions, and I would recommend you at least test this solution as it is fairly simple.
This is increasingly a SO problem, the down-voted answer is the correct one. SetWindowsHookEx() is indeed required to be able to catch the WM_ACTIVATE message that the activated window gets. But that requires a WH_CALLWNDPROC or WH_SHELL hook, hooks that cannot be implemented in C#. Catching those requires injecting a DLL in every process, a managed assembly cannot be injected into another process. The CLR cannot be initialized.
+1 for Noldorin to get him back to 0, that's all I can do. The OP needs to write his code in unmanaged C/C++, creating a DLL and use a standard IPC mechanism like pipes or sockets to notify the host app. Or poll, much easier.
I once wrote a small app that did this to keep track of my own work habits. What I did was call GetForegroundWindow() periodically (every 5 seconds or something) and noted the application that is running. You can get a lot of information from the window handle, not just the title but all the way down to the actual process that created it.
This is what I did using Java's JNA:
final HWND child = User32Ext.INSTANCE.GetForegroundWindow();
final int length = User32.INSTANCE.GetWindowTextLength(child) * 2;
final byte[] buffer = new byte[length];
User32.INSTANCE.GetWindowText(child, buffer, length);
title = new String(buffer, Charset.forName("UTF-16LE"));
where User32Ext is an extension I did because User32 (in JNA's distribution) doesn't have the interface for:
LRESULT callback(int nCode, WPARAM wParam, LPARAM lParam);
I'm periodically polling the active window, since I couldn't use the HCBT_SETFOCUS hook as mentioned in http://msdn.microsoft.com/en-us/library/ms997537.aspx, and I'll be very interested if someone comes up with the solution.

Categories

Resources