-1

I am trying to disable windows keys. Bt while running the application i get an error "CallbackOnCollectedDelegate was detected" Below is my code

Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As LowLevelKeyboardProcDelegate, ByVal hMod As IntPtr, ByVal dwThreadId As Integer) As IntPtr
Declare Function UnhookWindowsHookEx Lib "user32" Alias "UnhookWindowsHookEx" (ByVal hHook As IntPtr) As Boolean
Declare Function CallNextHookEx Lib "user32" Alias "CallNextHookEx" (ByVal hHook As IntPtr, ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
Delegate Function LowLevelKeyboardProcDelegate(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer

Const WH_KEYBOARD_LL As Integer = 13

Structure KBDLLHOOKSTRUCT
    Dim vkCode As Integer
    Dim scanCode As Integer
    Dim flags As Integer
    Dim time As Integer
    Dim dwExtraInfo As Integer
End Structure

Dim intLLKey As IntPtr

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    intLLKey = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, IntPtr.Zero, 0)
End Sub

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    UnhookWindowsHookEx(intLLKey)
End Sub

Private Function LowLevelKeyboardProc(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer
    Dim blnEat As Boolean = False
    Select Case wParam
        Case 256, 257, 260, 261
            'Alt+Tab, Alt+Esc, Ctrl+Esc, Windows Key    
            blnEat = ((lParam.vkCode = 9) AndAlso (lParam.flags = 32)) Or
            ((lParam.vkCode = 27) AndAlso (lParam.flags = 32)) Or
            ((lParam.vkCode = 27) AndAlso (lParam.flags = 0)) Or
            ((lParam.vkCode = 91) AndAlso (lParam.flags = 1)) Or
            ((lParam.vkCode = 92) AndAlso (lParam.flags = 1))
    End Select

    If blnEat = True Then
        Return 1
    Else
        Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
    End If
End Function

Any help is very much appreciated

Louisa
  • 3
  • 2
  • Can you show the rest of the error message? How to you run the code? – Kristoffer Bohmann Feb 28 '16 at 20:30
  • This is the full error message "Managed Debugging Assistant 'CallbackOnCollectedDelegate' has detected a problem in 'C:\Users\Louisa\Documents\Visual Studio 2015\Projects\Amus\Amus\bin\Debug\Amus.vshost.exe'. Additional information: A callback was made on a garbage collected delegate of type 'Amus!Amus.Form1+LowLevelKeyboardProcDelegate::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called." – Louisa Feb 28 '16 at 20:33

1 Answers1

2

The issue is the same as this post. The difference being that they're using C#. However, VB is doing the same thing; generating a delegate for you. For reference, this is what the decompiled code looks like in your form's Load event.

Private Sub Form1_Load(sender As Object, e As EventArgs)
    Me.intLLKey = Form1.SetWindowsHookEx(13, New Form1.LowLevelKeyboardProcDelegate(Me.LowLevelKeyboardProc), IntPtr.Zero, 0)
End Sub

Note that it's creating a LowLevelKeyboardProcDelegate delegate for you. I won't completely rehash @HansPassant's answer here, as he does an excellent job describing the problem and solution; only say that you'll need to store your own reference to the LowLevelKeyboardProcDelegate delegate.

Community
  • 1
  • 1
cokeman19
  • 2,405
  • 1
  • 25
  • 40
  • The problem is that i am not conversant with C#. i only know vb.net – Louisa Feb 28 '16 at 22:05
  • @Louisa Then use one of the many C# to VB converters to translate the code in the answer to VB. C# and VB do essentially the same things and code in one language can usually be translated into the other. – Blackwood Feb 28 '16 at 22:29
  • 1
    While my sentiment is with @Blackwood (e.g. ILSpy), conceptually, what you need to do is assign the result of `New LowLevelKeyboardProcDelegate(LowLevelKeyboardProc)` to a member variable, then use that variable as an argument in your call to `SetWindowsHookEx`. This will prevent your callback delegate from being garage collected. – cokeman19 Feb 28 '16 at 22:38
  • Thank you all @cokeman19,@Blackwood. I very much appreciate the help you offered. After a long struggle, it has finally worked. No more errors. – Louisa Feb 29 '16 at 04:07
  • Great! I'm glad to hear it. – cokeman19 Feb 29 '16 at 14:14