smad007
asked on
Paul Kimmel's Ctrl+Alt+Del Trapping Code Does Not Work for VB.NET Newbie
I want to trap Ctrl+Alt+Del and Ctrl+Esc and related keyboard sequences from my VB.NET app. In researching this I came across Paul Kimmel's very informitive and well-written article Managing Low-Level Keyboard Hooks in VB .NET at http://www.developer.com/net/vb/article.php/2193301 and I thought all of my problems were solved.
Unfortunately, the code that he provided in his article did not work for me and I'm trying to figure out why. I'm using .NET beta 2. As Mr. Kimmel suggested I copied and pasted his code into a new module in my solution called Keyboard, then from the click of a button on my main form I call Keyboard.HookKeyboard() and nothing happens.
In stepping through the code I can see that the code:
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss embly.GetM odules()(0 )).ToInt32 , 0)
in sub HookKeyboard is not working. After executing this line the value of KeyboardHandle = 0 and the value of Err.LastDLLError = 127. This question is probably not very difficult as I'm pretty sure Mr Kimmel's code would work if I were using it properly. But I'm a newbie with VB.NET and I think I'm doing something wrong. If anyone has any idea please let me know.
Thanks
Unfortunately, the code that he provided in his article did not work for me and I'm trying to figure out why. I'm using .NET beta 2. As Mr. Kimmel suggested I copied and pasted his code into a new module in my solution called Keyboard, then from the click of a button on my main form I call Keyboard.HookKeyboard() and nothing happens.
In stepping through the code I can see that the code:
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss
in sub HookKeyboard is not working. After executing this line the value of KeyboardHandle = 0 and the value of Err.LastDLLError = 127. This question is probably not very difficult as I'm pretty sure Mr Kimmel's code would work if I were using it properly. But I'm a newbie with VB.NET and I think I'm doing something wrong. If anyone has any idea please let me know.
Thanks
I had been playing around with hooking up to the ape-grip (as we Germans call it :-) about a year ago.
Without having read the article by PK that you mentioned - all my experiments and research resulted in it just not being possible with i.e. Windows XP as it happens "beyond a trappable level". :-(
FWIW - here's an another article on hooking (MSDN-magazine): http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/
Without having read the article by PK that you mentioned - all my experiments and research resulted in it just not being possible with i.e. Windows XP as it happens "beyond a trappable level". :-(
FWIW - here's an another article on hooking (MSDN-magazine): http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/
ASKER
To try and spark more interest in this thread I've included the code listing from the article mentioned above. Here it is:
'Listing 2: The complete revised listing for implementing low-level keyboard hooks.
Imports System.Runtime.InteropServ ices
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Module Keyboard
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Integer) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
ByVal lpfn As KeyboardHookDelegate, ByVal hmod As Integer, _
ByVal dwThreadId As Integer) As Integer
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Integer) As Integer
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Integer, _
ByVal nCode As Integer, _
ByVal wParam As Integer, _
ByVal lParam As KBDLLHOOKSTRUCT) As Integer
Public Structure KBDLLHOOKSTRUCT
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure
' Low-Level Keyboard Constants
Private Const HC_ACTION As Integer = 0
Private Const LLKHF_EXTENDED As Integer = &H1
Private Const LLKHF_INJECTED As Integer = &H10
Private Const LLKHF_ALTDOWN As Integer = &H20
Private Const LLKHF_UP As Integer = &H80
' Virtual Keys
Public Const VK_TAB = &H9
Public Const VK_CONTROL = &H11
Public Const VK_ESCAPE = &H1B
Public Const VK_DELETE = &H2E
Private Const WH_KEYBOARD_LL As Integer = 13&
Public KeyboardHandle As Integer
' Implement this function to block as many
' key combinations as you'd like
Public Function IsHooked( _
ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
Debug.WriteLine("Hookstruc t.vkCode: " & Hookstruct.vkCode)
Debug.WriteLine(Hookstruct .vkCode = VK_ESCAPE)
Debug.WriteLine(Hookstruct .vkCode = VK_TAB)
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(GetAsyncKeyState(VK_ CONTROL) _
And &H8000) Then
Call HookedState("Ctrl + Esc blocked")
Return True
End If
If (Hookstruct.vkCode = VK_TAB) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Tab blockd")
Return True
End If
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Escape blocked")
Return True
End If
Return False
End Function
Private Sub HookedState(ByVal Text As String)
Debug.WriteLine(Text)
End Sub
Public Function KeyboardCallback(ByVal Code As Integer, _
ByVal wParam As Integer, _
ByRef lParam As KBDLLHOOKSTRUCT) As Integer
If (Code = HC_ACTION) Then
Debug.WriteLine("Calling IsHooked")
If (IsHooked(lParam)) Then
Return 1
End If
End If
Return CallNextHookEx(KeyboardHan dle, _
Code, wParam, lParam)
End Function
Public Delegate Function KeyboardHookDelegate( _
ByVal Code As Integer, _
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) _
As Integer
<MarshalAs(UnmanagedType.F unctionPtr )> _
Private callback As KeyboardHookDelegate
Public Sub HookKeyboard()
callback = New KeyboardHookDelegate(Addre ssOf KeyboardCallback)
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss embly.GetM odules()(0 )).ToInt32 , 0)
Call CheckHooked()
End Sub
Public Sub CheckHooked()
If (Hooked()) Then
Debug.WriteLine("Keyboard hooked")
Else
Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
End If
End Sub
Private Function Hooked()
Hooked = KeyboardHandle <> 0
End Function
Public Sub UnhookKeyboard()
If (Hooked()) Then
Call UnhookWindowsHookEx(Keyboa rdHandle)
End If
End Sub
End Module
And here is Mr. Kimmel's directions for making use of this code:
"You can copy and paste the code in listing 2 directly into a module to experiment with it. Call HookKeyboard to begin intercepting the three defined key combinations and UnhookKeyboard to restore the old keyboard state."
As directed, I added a module to my solution and pasted this code into it. Then on my main form I have a button that when pressed calls HookKeyboard. Now in stepping through the code I see that when line 2 of HookKeyboard finishes executing the value of KeyboardHandle = 0. Of course the subsequent calls to CheckHooked() and then Hooked() show that the keyboard has not been hooked. Also, I have noticed that the value of Err.LastDLLError = 127.
Hopefully someone has some idea where I'm going wrong.
Thanks
'Listing 2: The complete revised listing for implementing low-level keyboard hooks.
Imports System.Runtime.InteropServ
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Module Keyboard
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Integer) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
ByVal lpfn As KeyboardHookDelegate, ByVal hmod As Integer, _
ByVal dwThreadId As Integer) As Integer
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Integer) As Integer
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Integer, _
ByVal nCode As Integer, _
ByVal wParam As Integer, _
ByVal lParam As KBDLLHOOKSTRUCT) As Integer
Public Structure KBDLLHOOKSTRUCT
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure
' Low-Level Keyboard Constants
Private Const HC_ACTION As Integer = 0
Private Const LLKHF_EXTENDED As Integer = &H1
Private Const LLKHF_INJECTED As Integer = &H10
Private Const LLKHF_ALTDOWN As Integer = &H20
Private Const LLKHF_UP As Integer = &H80
' Virtual Keys
Public Const VK_TAB = &H9
Public Const VK_CONTROL = &H11
Public Const VK_ESCAPE = &H1B
Public Const VK_DELETE = &H2E
Private Const WH_KEYBOARD_LL As Integer = 13&
Public KeyboardHandle As Integer
' Implement this function to block as many
' key combinations as you'd like
Public Function IsHooked( _
ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
Debug.WriteLine("Hookstruc
Debug.WriteLine(Hookstruct
Debug.WriteLine(Hookstruct
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(GetAsyncKeyState(VK_
And &H8000) Then
Call HookedState("Ctrl + Esc blocked")
Return True
End If
If (Hookstruct.vkCode = VK_TAB) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Tab blockd")
Return True
End If
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Escape blocked")
Return True
End If
Return False
End Function
Private Sub HookedState(ByVal Text As String)
Debug.WriteLine(Text)
End Sub
Public Function KeyboardCallback(ByVal Code As Integer, _
ByVal wParam As Integer, _
ByRef lParam As KBDLLHOOKSTRUCT) As Integer
If (Code = HC_ACTION) Then
Debug.WriteLine("Calling IsHooked")
If (IsHooked(lParam)) Then
Return 1
End If
End If
Return CallNextHookEx(KeyboardHan
Code, wParam, lParam)
End Function
Public Delegate Function KeyboardHookDelegate( _
ByVal Code As Integer, _
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) _
As Integer
<MarshalAs(UnmanagedType.F
Private callback As KeyboardHookDelegate
Public Sub HookKeyboard()
callback = New KeyboardHookDelegate(Addre
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss
Call CheckHooked()
End Sub
Public Sub CheckHooked()
If (Hooked()) Then
Debug.WriteLine("Keyboard hooked")
Else
Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
End If
End Sub
Private Function Hooked()
Hooked = KeyboardHandle <> 0
End Function
Public Sub UnhookKeyboard()
If (Hooked()) Then
Call UnhookWindowsHookEx(Keyboa
End If
End Sub
End Module
And here is Mr. Kimmel's directions for making use of this code:
"You can copy and paste the code in listing 2 directly into a module to experiment with it. Call HookKeyboard to begin intercepting the three defined key combinations and UnhookKeyboard to restore the old keyboard state."
As directed, I added a module to my solution and pasted this code into it. Then on my main form I have a button that when pressed calls HookKeyboard. Now in stepping through the code I see that when line 2 of HookKeyboard finishes executing the value of KeyboardHandle = 0. Of course the subsequent calls to CheckHooked() and then Hooked() show that the keyboard has not been hooked. Also, I have noticed that the value of Err.LastDLLError = 127.
Hopefully someone has some idea where I'm going wrong.
Thanks
ASKER
Just wanted to say thanks to Olaf for the article link. I enjoyed reading it. This is a very interesting subject and any additional information is usefull and welcome.
So thanks Olaf.
So thanks Olaf.
Hi smad007,
you sure are welcome.
I tried your sample now on a WindowsXP SP2 machine (auto-updates on). Other than the author, my default setting is to have Option Explicit and Option Strict turned on. If you do so, you'll have to change the VK_*-constants to be of Integer-type and the Hooked-function will have to be setup to return a Boolean. Maybe that'll do the trick on your PC as well - I simply don't know what the compiler would do with the VK-constants, but they surely should be integers!
Anyway, with that, the module actually did get a handle and hence the hook worked. While running (I suggest not to set any breakpoints in the KeyboardCallback-function as that might end up in just about anything "unhealthy"), I can see that Alt-Tab actually is stopped.
However, I didn't manage to set the hook to fire on Ctrl-Alt-Del. In Paul's module, the Alt-key declared private but still being used in the flags-var within the KBDLLHOOKSTRUCT. Setting the flag to hex 20 at least didn't do the trick. Have you digged further? I'm a little short on time this week so, sorry, I just didn't have the time to spend more than some ten minutes with the code. :-( And it won't get better until the end of next week as I'm in a hurry of getting everything done before I get to Amsterdam for TechEd 05.
Cheers,
Olaf
you sure are welcome.
I tried your sample now on a WindowsXP SP2 machine (auto-updates on). Other than the author, my default setting is to have Option Explicit and Option Strict turned on. If you do so, you'll have to change the VK_*-constants to be of Integer-type and the Hooked-function will have to be setup to return a Boolean. Maybe that'll do the trick on your PC as well - I simply don't know what the compiler would do with the VK-constants, but they surely should be integers!
Anyway, with that, the module actually did get a handle and hence the hook worked. While running (I suggest not to set any breakpoints in the KeyboardCallback-function as that might end up in just about anything "unhealthy"), I can see that Alt-Tab actually is stopped.
However, I didn't manage to set the hook to fire on Ctrl-Alt-Del. In Paul's module, the Alt-key declared private but still being used in the flags-var within the KBDLLHOOKSTRUCT. Setting the flag to hex 20 at least didn't do the trick. Have you digged further? I'm a little short on time this week so, sorry, I just didn't have the time to spend more than some ten minutes with the code. :-( And it won't get better until the end of next week as I'm in a hurry of getting everything done before I get to Amsterdam for TechEd 05.
Cheers,
Olaf
ASKER
Hi Olaf,
As you suggested I turned on option explicit and strict and added the "as integer" and "as boolean" where necessary, but it still does the same thing. The keyboard is not being hooked.
I'm running this code on Windows 2000 SP4 and VB.NET beta 2. Unfortunately I have not gotten any further with this issue, but I'll keep trying. Thanks again for your input.
As you suggested I turned on option explicit and strict and added the "as integer" and "as boolean" where necessary, but it still does the same thing. The keyboard is not being hooked.
I'm running this code on Windows 2000 SP4 and VB.NET beta 2. Unfortunately I have not gotten any further with this issue, but I'll keep trying. Thanks again for your input.
Hi smad007;
The Ctrl+Alt+Del key combination can not be trapped because it is a hard wired interrupt from the keyboard. But the Ctrl + Esc can be trapped.
Create a Module in the project you want to trap keyboard combinations from, call it Keyboard. Then copy this code into a module replacing the stub code that Microsoft create for you. Then in your main form load event call the the sub "HookKeyboard()" and in your form closing event call the sub "UnhookKeyboard()" very important.
This should work on Windows 2000 with no problem, not sure about VB .Net Beta 2
This code is basically the same as Olaf_Rabbachin had instructed you to make. I have also added some comments about removing some code to unblock key combination that the author had added but that you may not want in, it is in function IsHooked.
Good Luck
Imports System.Runtime.InteropServ ices
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Module Keyboard
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Integer) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
ByVal lpfn As KeyboardHookDelegate, ByVal hmod As Integer, _
ByVal dwThreadId As Integer) As Integer
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Integer) As Integer
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Integer, _
ByVal nCode As Integer, _
ByVal wParam As Integer, _
ByVal lParam As KBDLLHOOKSTRUCT) As Integer
Public Structure KBDLLHOOKSTRUCT
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure
' Low-Level Keyboard Constants
Private Const HC_ACTION As Integer = 0
Private Const LLKHF_EXTENDED As Integer = &H1
Private Const LLKHF_INJECTED As Integer = &H10
Private Const LLKHF_ALTDOWN As Integer = &H20
Private Const LLKHF_UP As Integer = &H80
' Virtual Keys
Public Const VK_TAB As Integer = &H9
Public Const VK_CONTROL As Integer = &H11
Public Const VK_ESCAPE As Integer = &H1B
Public Const VK_DELETE As Integer = &H2E
Private Const WH_KEYBOARD_LL As Integer = 13&
Public KeyboardHandle As Integer
' Implement this function to block as many
' key combinations as you'd like
Public Function IsHooked( _
ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
Debug.WriteLine("Hookstruc t.vkCode: " & Hookstruct.vkCode)
Debug.WriteLine(Hookstruct .vkCode = VK_ESCAPE)
Debug.WriteLine(Hookstruct .vkCode = VK_TAB)
' Remove any of the If statement for those key combination
' you do not want to block. Add an If statement for those
' key combination you do want to block.
' Blocks the Control + Escape keys combination
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(GetAsyncKeyState(VK_ CONTROL) _
And &H8000) Then
Call HookedState("Ctrl + Esc blocked")
Return True
End If
' Blocks the Alt + Tab keys combination
If (Hookstruct.vkCode = VK_TAB) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Tab blockd")
Return True
End If
' Blocks the Alt + Escape keys combination
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Escape blocked")
Return True
End If
Return False
End Function
Private Sub HookedState(ByVal Text As String)
Debug.WriteLine(Text)
End Sub
Public Function KeyboardCallback(ByVal Code As Integer, _
ByVal wParam As Integer, _
ByRef lParam As KBDLLHOOKSTRUCT) As Integer
If (Code = HC_ACTION) Then
Debug.WriteLine("Calling IsHooked")
If (IsHooked(lParam)) Then
Return 1
End If
End If
Return CallNextHookEx(KeyboardHan dle, _
Code, wParam, lParam)
End Function
Public Delegate Function KeyboardHookDelegate( _
ByVal Code As Integer, _
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) _
As Integer
<MarshalAs(UnmanagedType.F unctionPtr )> _
Private callback As KeyboardHookDelegate
Public Sub HookKeyboard()
callback = New KeyboardHookDelegate(Addre ssOf KeyboardCallback)
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss embly.GetM odules()(0 )).ToInt32 , 0)
Call CheckHooked()
End Sub
Public Sub CheckHooked()
If (Hooked()) Then
Debug.WriteLine("Keyboard hooked")
Else
Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
End If
End Sub
Private Function Hooked() As Boolean
Hooked = KeyboardHandle <> 0
End Function
Public Sub UnhookKeyboard()
If (Hooked()) Then
Call UnhookWindowsHookEx(Keyboa rdHandle)
End If
End Sub
End Module
The Ctrl+Alt+Del key combination can not be trapped because it is a hard wired interrupt from the keyboard. But the Ctrl + Esc can be trapped.
Create a Module in the project you want to trap keyboard combinations from, call it Keyboard. Then copy this code into a module replacing the stub code that Microsoft create for you. Then in your main form load event call the the sub "HookKeyboard()" and in your form closing event call the sub "UnhookKeyboard()" very important.
This should work on Windows 2000 with no problem, not sure about VB .Net Beta 2
This code is basically the same as Olaf_Rabbachin had instructed you to make. I have also added some comments about removing some code to unblock key combination that the author had added but that you may not want in, it is in function IsHooked.
Good Luck
Imports System.Runtime.InteropServ
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Module Keyboard
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Integer) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" _
Alias "SetWindowsHookExA" (ByVal idHook As Integer, _
ByVal lpfn As KeyboardHookDelegate, ByVal hmod As Integer, _
ByVal dwThreadId As Integer) As Integer
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Integer) As Integer
Private Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Integer, _
ByVal nCode As Integer, _
ByVal wParam As Integer, _
ByVal lParam As KBDLLHOOKSTRUCT) As Integer
Public Structure KBDLLHOOKSTRUCT
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure
' Low-Level Keyboard Constants
Private Const HC_ACTION As Integer = 0
Private Const LLKHF_EXTENDED As Integer = &H1
Private Const LLKHF_INJECTED As Integer = &H10
Private Const LLKHF_ALTDOWN As Integer = &H20
Private Const LLKHF_UP As Integer = &H80
' Virtual Keys
Public Const VK_TAB As Integer = &H9
Public Const VK_CONTROL As Integer = &H11
Public Const VK_ESCAPE As Integer = &H1B
Public Const VK_DELETE As Integer = &H2E
Private Const WH_KEYBOARD_LL As Integer = 13&
Public KeyboardHandle As Integer
' Implement this function to block as many
' key combinations as you'd like
Public Function IsHooked( _
ByRef Hookstruct As KBDLLHOOKSTRUCT) As Boolean
Debug.WriteLine("Hookstruc
Debug.WriteLine(Hookstruct
Debug.WriteLine(Hookstruct
' Remove any of the If statement for those key combination
' you do not want to block. Add an If statement for those
' key combination you do want to block.
' Blocks the Control + Escape keys combination
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(GetAsyncKeyState(VK_
And &H8000) Then
Call HookedState("Ctrl + Esc blocked")
Return True
End If
' Blocks the Alt + Tab keys combination
If (Hookstruct.vkCode = VK_TAB) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Tab blockd")
Return True
End If
' Blocks the Alt + Escape keys combination
If (Hookstruct.vkCode = VK_ESCAPE) And _
CBool(Hookstruct.flags And _
LLKHF_ALTDOWN) Then
Call HookedState("Alt + Escape blocked")
Return True
End If
Return False
End Function
Private Sub HookedState(ByVal Text As String)
Debug.WriteLine(Text)
End Sub
Public Function KeyboardCallback(ByVal Code As Integer, _
ByVal wParam As Integer, _
ByRef lParam As KBDLLHOOKSTRUCT) As Integer
If (Code = HC_ACTION) Then
Debug.WriteLine("Calling IsHooked")
If (IsHooked(lParam)) Then
Return 1
End If
End If
Return CallNextHookEx(KeyboardHan
Code, wParam, lParam)
End Function
Public Delegate Function KeyboardHookDelegate( _
ByVal Code As Integer, _
ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) _
As Integer
<MarshalAs(UnmanagedType.F
Private callback As KeyboardHookDelegate
Public Sub HookKeyboard()
callback = New KeyboardHookDelegate(Addre
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss
Call CheckHooked()
End Sub
Public Sub CheckHooked()
If (Hooked()) Then
Debug.WriteLine("Keyboard hooked")
Else
Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
End If
End Sub
Private Function Hooked() As Boolean
Hooked = KeyboardHandle <> 0
End Function
Public Sub UnhookKeyboard()
If (Hooked()) Then
Call UnhookWindowsHookEx(Keyboa
End If
End Sub
End Module
ASKER
Hello Fernando,
I have followed your instructions but alas, it still does not work. Maybe this is a beta 2 thing as I have you, Olaf, and Paul Kimmel all saying this code works and I believe all three of you are reliable sources.
Using the code you posted above and calling HookKeyboard() from Form1_Load() I trace the execution and again I see that after the line:
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss embly.GetM odules()(0 )).ToInt32 , 0)
in HookKeyboard() finishes executing the value of KeyboardHandle == 0, which I interpret to mean the hook didn't work.
One slight difference though, now I can see the value of Err.LastDLLError == 0, Err.Number == 0, and
Err.Description == "". So it's like the hook does not work, but there is no error registering.
I am running on Windows 2000 Version 5, Service Pack 4 so I don't know why this code seems to work for everyone except me. It must be some sort of problem with beta 2 I guess?
Thanks
I have followed your instructions but alas, it still does not work. Maybe this is a beta 2 thing as I have you, Olaf, and Paul Kimmel all saying this code works and I believe all three of you are reliable sources.
Using the code you posted above and calling HookKeyboard() from Form1_Load() I trace the execution and again I see that after the line:
KeyboardHandle = SetWindowsHookEx( _
WH_KEYBOARD_LL, callback, _
Marshal.GetHINSTANCE( _
[Assembly].GetExecutingAss
in HookKeyboard() finishes executing the value of KeyboardHandle == 0, which I interpret to mean the hook didn't work.
One slight difference though, now I can see the value of Err.LastDLLError == 0, Err.Number == 0, and
Err.Description == "". So it's like the hook does not work, but there is no error registering.
I am running on Windows 2000 Version 5, Service Pack 4 so I don't know why this code seems to work for everyone except me. It must be some sort of problem with beta 2 I guess?
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Fernando,
Again you have come to the rescue. The file from ForumHelp-Temp worked and from that I was able to get the keytrapping in my application. The code looks similar to what I had before, so I'm not sure what you did differently, but the important thing is it works now. I can now trap Ctrl + Esc, Ctrl + Shift + Esc, Alt + Tab, Alt + F4, Alt + Esc, and the left and right Windows keys.
As you suspected this method does not trap Ctrl + Alt + Del, but I have had some feedback that this is possible on Windows NT systems through GINA stubs and through the registry, so I will explore these avenues to try to trap that pesky key combination.
Thank you for your diligence,
Adam
Again you have come to the rescue. The file from ForumHelp-Temp worked and from that I was able to get the keytrapping in my application. The code looks similar to what I had before, so I'm not sure what you did differently, but the important thing is it works now. I can now trap Ctrl + Esc, Ctrl + Shift + Esc, Alt + Tab, Alt + F4, Alt + Esc, and the left and right Windows keys.
As you suspected this method does not trap Ctrl + Alt + Del, but I have had some feedback that this is possible on Windows NT systems through GINA stubs and through the registry, so I will explore these avenues to try to trap that pesky key combination.
Thank you for your diligence,
Adam
Glad to help. Let me know if you find how to trap the Ctrl+Alt+Del I would like to know.
Good Luck;
Fernando
Good Luck;
Fernando
ASKER
I did manage to find a way to trap Ctrl + Alt + Del. Fire up regedit and change the value of the key:
HKEY_LOCAL_MACHINE\SOFTWAR E\Microsof t\Windows NT\CurrentVersion\Winlogon \AutoAdmin Logon, from whatever it is (0 or 1), set it to 2.
This may seem very weird, here is an article which explains a little bit (but not really).
http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=35997&lngWId=-10
The important thing is...it works!
HKEY_LOCAL_MACHINE\SOFTWAR
This may seem very weird, here is an article which explains a little bit (but not really).
http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=35997&lngWId=-10
The important thing is...it works!
Great news - cheers!
Hi Adam;
Get to hear it and thanks for the link to the article.
Fernando
Get to hear it and thanks for the link to the article.
Fernando
ASKER
Well, I increased the points. As far as the article goes I highly recommend reading it (even if you don't want to post a reply to my question). It is very well-written, and very interesting even from a strictly academic point of view. I think this subject (hooking) is very interesting and I wish I understood it better. I found Paul Kimmel's article to be far and away the best explanation of hooking keystrokes that I've found on the web in over a day of searching.
I hope this thread gets some action soon...