Asked by:

SetWindowsHookEx works in Net 2 but not in Net 4

Question

I am developing an application that will engage a bar code scanner and will need to be listening for input even when it is not the active application or from a separate thread from within the application. I can get a handle to the hook when I set the
project to compile for Net 2. When I set my project to compile for Net 4 I cannot get a handle from the SetWindowsHookEx. Same code, no changes at all. While obviously I can get a working DLL out of this it really is buggin the ____ out of
me. Additionally, if one of my colegues needs to adjust this DLL in the future and does not know, they may compile it in Net 4. I also have no idea what will be the effects if I reference this DLL in another project that is compiled in Net 4.
Lastly, I am worried that I may encounter more difficulties like this in the future if I cannot figure out what the difference is. Does anyone know why this is or what the solution might be?

Public Event KeyDown(ByRef TheKeyArgs As Windows.Forms.KeyEventArgs)
Public Event KeyPress(ByRef TheKeyArgs As Windows.Forms.KeyEventArgs)
Public Event KeyUp(ByRef TheKeyArgs As Windows.Forms.KeyEventArgs)

Private Structure KBDLLHOOKSTRUCT
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure

#End Region

#Region " Constructors, Destructors and Load Methods "

Public Sub New()

Try

Catch ex As Exception
Throw ex
End Try

End Sub

Public Overridable Sub Dispose() Implements IDisposable.Dispose

Try
If Not (Disposed = True) Then
Disposed = True
If Not (KeyboardHandle = 0) Then UnhookWindowsHookEx(KeyboardHandle)
Else
Throw New ObjectDisposedException("KeyboardHook")
End If

Catch ex As Exception
Throw ex
End Try

End Sub

Protected Overrides Sub Finalize()

Try
MyBase.Finalize()

If Not Disposed Then
Dispose()
End If

Catch ex As Exception
Throw ex
End Try

End Sub

#End Region

#Region " Methods - Primary "

Public Function StartListening() As Boolean

Try
'// The first argument to SetWindowsHookEx Sets the Type of Hook.
'// The second argument is the tagged delegate that contains the address of our local callback method.
'// The third argument is the handle (hWnd) of the application doing the hooking
'// The fourth argument is the thread to listen on. Passing 0 indicates all threads.

Thanks for your reply. I changed my code and now it works. I noticed the
following :

hMod [in]
HINSTANCE

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.

Notice NULL setting for running this from the same process -> So in my call I now pass a
IntPtr.Zero (In my .Net 4.0 code)

and it works since the thread is created by the current process. I am not sure if this was like this before or not, but now it is working.

Edit:Above works great in Windows 7, but not in Windows XP, setting it to System.Diagnostics.Process.GetCurrentProcess().MainModule.BaseAddress will work in both (thanks to Patrick Klug for suggesting this)