Question

I have developed a program that contains a keyboard hook (is in this webpage) and it plays a sound when the user press a key.

When I debug it, it works perfectly, except sometimes this error appears:

No se controló System.InvalidOperationException
HResult=-2146233079
Message=Error al crear el formulario. Consulte Exception.InnerException para obtener más detalles. Error: Could not set keyboard hook
Source=CBAS
StackTrace:
en CBAS.My.MyProject.MyForms.Create__Instance__[T](T Instance) en 17d14f5c-a337-4978-8281-53493378c1071.vb:línea 190
en CBAS.My.MyProject.MyForms.get_Form1()
en CBAS.My.MyApplication.OnCreateMainForm() en C:\Users\win8\Desktop\CBAS\CBAS\My Project\Application.Designer.vb:línea 35
en Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.OnRun()
en Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.DoApplicationModel()
en Microsoft.VisualBasic.ApplicationServices.WindowsF ormsApplicationBase.Run(String[] commandLine)
en CBAS.My.MyApplication.Main(String[] Args) en 17d14f5c-a337-4978-8281-53493378c1071.vb:línea 81
en System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
en System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
en Microsoft.VisualStudio.HostingProcess.HostProc.Run UsersAssembly()
en System.Threading.ThreadHelper.ThreadStart_Context( Object state)
en System.Threading.ExecutionContext.RunInternal(Exec utionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
en System.Threading.ExecutionContext.Run(ExecutionCon text executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
en System.Threading.ExecutionContext.Run(ExecutionCon text executionContext, ContextCallback callback, Object state)
en System.Threading.ThreadHelper.ThreadStart()
InnerException: 
HResult=-2146233088
Message=Could not set keyboard hook
Source=CBAS
StackTrace:
en CBAS.KeyboardHook..ctor() en C:\Users\win8\Desktop\CBAS\CBAS\KeyboardHook.vb:lí nea 57
en CBAS.Form1..ctor() en C:\Users\win8\Desktop\CBAS\CBAS\Form1.vb:línea 8
InnerException: )

But when I publish it, execute it and I press a key, this error always appear:

"Application1 has stopped working, Windows is collecting more information about the problem..."

I don't know why.

How can I fix it?

In the WER (windows error reporting) file, this appears (it's in Spanish because I'm Spanish)

Version=1
EventType=CLR20r3
EventTime=130379893951236939
ReportType=2
Consent=1
UploadTime=130379893952509742
ReportIdentifier=de74a3fd-9fc5-11e3-bf5a-2016d88a811a
IntegratorReportIdentifier=de74a3fc-9fc5-11e3-bf5a-2016d88a811a
WOW64=1
NsAppName=Application1.exe
Response.BucketId=40a1e70aa352cd3ac6cc9fb760f9bba0
Response.BucketTable=5
Response.LegacyBucketId=94505433654
Response.type=4
Response.CabId=94493168456
Sig[0].Name=Firma del problema 01
Sig[0].Value=application1.exe
Sig[1].Name=Firma del problema 02
Sig[1].Value=1.0.0.0
Sig[2].Name=Firma del problema 03
Sig[2].Value=530f5ce4
Sig[3].Name=Firma del problema 04
Sig[3].Value=System
Sig[4].Name=Firma del problema 05
Sig[4].Value=4.0.30319.18045
Sig[5].Name=Firma del problema 06
Sig[5].Value=5126f9e5
Sig[6].Name=Firma del problema 07
Sig[6].Value=1312
Sig[7].Name=Firma del problema 08
Sig[7].Value=43
Sig[8].Name=Firma del problema 09
Sig[8].Value=System.IO.FileNotFoundException
DynamicSig[1].Name=Versión del sistema operativo
DynamicSig[1].Value=6.2.9200.2.0.0.768.101
DynamicSig[2].Name=Id. de configuración regional
DynamicSig[2].Value=3082
DynamicSig[22].Name=Información adicional 1
DynamicSig[22].Value=ad52
DynamicSig[23].Name=Información adicional 2
DynamicSig[23].Value=ad5243c3e40479b968754b46da71fc1d
DynamicSig[24].Name=Información adicional 3
DynamicSig[24].Value=cb3a
DynamicSig[25].Name=Información adicional 4
DynamicSig[25].Value=cb3ad7e6b5724be9ade53a06384fee8d
UI[2]=C:\Users\yo\Desktop\publish\Application Files\Application1_1_0_0_12\Application1.exe
UI[3]=Application1 dejó de funcionar
UI[4]=Windows puede buscar una solución en línea al problema.
UI[5]=Buscar una solución en línea y cerrar el programa
UI[6]=Buscar una solución en línea más tarde y cerrar el programa
UI[7]=Cerrar el programa
LoadedModule[0]=C:\Users\yo\Desktop\publish\Application Files\Application1_1_0_0_12\Application1.exe
LoadedModule[1]=C:\windows\SYSTEM32\ntdll.dll
LoadedModule[2]=C:\windows\SYSTEM32\MSCOREE.DLL
LoadedModule[3]=C:\windows\SYSTEM32\KERNEL32.dll
LoadedModule[4]=C:\windows\SYSTEM32\KERNELBASE.dll
LoadedModule[5]=C:\windows\system32\apphelp.dll
LoadedModule[6]=C:\windows\SYSTEM32\ADVAPI32.dll
LoadedModule[7]=C:\windows\SYSTEM32\msvcrt.dll
LoadedModule[8]=C:\windows\SYSTEM32\sechost.dll
LoadedModule[9]=C:\windows\SYSTEM32\RPCRT4.dll
LoadedModule[10]=C:\windows\SYSTEM32\SspiCli.dll
LoadedModule[11]=C:\windows\SYSTEM32\CRYPTBASE.dll
LoadedModule[12]=C:\windows\SYSTEM32\bcryptPrimitives.dll
LoadedModule[13]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\msc oreei.dll
LoadedModule[14]=C:\windows\SYSTEM32\SHLWAPI.dll
LoadedModule[15]=C:\windows\SYSTEM32\USER32.dll
LoadedModule[16]=C:\windows\SYSTEM32\GDI32.dll
LoadedModule[17]=C:\windows\system32\IMM32.DLL
LoadedModule[18]=C:\windows\SYSTEM32\MSCTF.dll
LoadedModule[19]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr .dll
LoadedModule[20]=C:\windows\SYSTEM32\MSVCR110_CLR0400.dll
LoadedModule[21]=C:\windows\assembly\NativeImages_v4.0.30319_32\ms corlib\391541c89ed7585fc7e8936c43cee387\mscorlib.n i.dll
LoadedModule[22]=C:\windows\SYSTEM32\ole32.dll
LoadedModule[23]=C:\windows\SYSTEM32\combase.dll
LoadedModule[24]=C:\windows\system32\uxtheme.dll
LoadedModule[25]=C:\windows\assembly\NativeImages_v4.0.30319_32\Sy stem\f0602360211041a6be208f0b4138dddd\System.ni.dl l
LoadedModule[26]=C:\windows\assembly\NativeImages_v4.0.30319_32\Sy stem.Core\bca236f576ea12db3a9191f4586a445a\System. Core.ni.dll
LoadedModule[27]=C:\windows\assembly\NativeImages_v4.0.30319_32\Mi crosoft.V9921e851#\544c2dc6a8eccbe94917fa495786d22 8\Microsoft.VisualBasic.ni.dll
LoadedModule[28]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr jit.dll
LoadedModule[29]=C:\windows\SYSTEM32\OLEAUT32.dll
LoadedModule[30]=C:\windows\assembly\NativeImages_v4.0.30319_32\Sy stem.Drawing\61be23d6a688188e3419a1eb46fc9d9d\Syst em.Drawing.ni.dll
LoadedModule[31]=C:\windows\assembly\NativeImages_v4.0.30319_32\Sy stem.Windows.Forms\11b4af16e791a6b0ada4a97d3e64e27 a\System.Windows.Forms.ni.dll
LoadedModule[32]=C:\windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.9200.16658_none_bf1 359a245f1cd12\comctl32.dll
LoadedModule[33]=C:\windows\SYSTEM32\dwmapi.dll
LoadedModule[34]=C:\windows\assembly\NativeImages_v4.0.30319_32\Sy stem.Runt73a1fc9d#\3ca3214971476bd8dfa50fb1ad771f6 9\System.Runtime.Remoting.ni.dll
LoadedModule[35]=C:\windows\WinSxS\x86_microsoft.windows.gdiplus_6 595b64144ccf1df_1.1.9200.16518_none_ba1cf6b7e09f19 18\gdiplus.dll
LoadedModule[36]=C:\windows\SYSTEM32\DWrite.dll
LoadedModule[37]=C:\windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.9200.16579_none_8937 eec6860750f5\comctl32.dll
LoadedModule[38]=C:\windows\SYSTEM32\winmm.dll
LoadedModule[39]=C:\windows\SYSTEM32\WINMMBASE.dll
LoadedModule[40]=C:\windows\SYSTEM32\cfgmgr32.dll
LoadedModule[41]=C:\windows\SYSTEM32\DEVOBJ.dll
LoadedModule[42]=C:\windows\SYSTEM32\CRYPTSP.dll
LoadedModule[43]=C:\windows\system32\rsaenh.dll
LoadedModule[44]=C:\windows\SYSTEM32\VERSION.dll
LoadedModule[45]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\dia symreader.dll
State[0].Key=Transport.DoneStage1
State[0].Value=1
File[0].CabName=WERInternalMetadata.xml
File[0].Path=WER3909.tmp.WERInternalMetadata.xml
File[0].Flags=851971
File[0].Type=5
File[0].Original.Path=C:\Users\win8\AppData\Local\temp\WE R3909.tmp.WERInternalMetadata.xml
File[1].CabName=triagedump.dmp
File[1].Path=WER44E2.tmp.dmp
File[1].Flags=2949123
File[1].Type=6
File[1].Original.Path=C:\Users\win8\AppData\Local\temp\WE R44E2.tmp.dmp
File[2].CabName=Report.cab
File[2].Path=Report.cab
File[2].Flags=196608
File[2].Type=9
File[2].Original.Path=Report.cab
FriendlyEventName=Dejó de funcionar
ConsentKey=CLR20r3
AppName=Application1
AppPath=C:\Users\yo\Desktop\publish\Application Files\Application1_1_0_0_12\Application1.exe
NsPartner=windows
NsGroup=windows8

In the form1 I have this code:

Imports System.Threading

Public Class Form1
    Dim iresult As Long
    Dim ResourceFilePathPrefix As String
    Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
    Private Declare Function mciExecute Lib "winmm.dll" (ByVal lpstrCommand As String) As Long
    Private WithEvents kbHook As New KeyboardHook
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        If System.Diagnostics.Debugger.IsAttached() Then
            ResourceFilePathPrefix = System.IO.Path.GetFullPath(Application.StartupPath & "\..\..\resources\")
        Else
            ResourceFilePathPrefix = Application.StartupPath & "\resources\"
        End If

    End Sub
    Private Sub kbHook_KeyDown(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyDown


        Select Case Key
            Case Keys.A
                My.Computer.Audio.Play(ResourceFilePathPrefix & "Sound1.wav")
            Case Keys.B
                My.Computer.Audio.Play(ResourceFilePathPrefix & "Sound2.wav")
            Case Keys.C
                My.Computer.Audio.Play(ResourceFilePathPrefix & "Sound3.wav")

        End Select
    End Sub

End Class

And this is the code from the web:

Imports System.Runtime.InteropServices

Public Class KeyboardHook

    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Overloads Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As KBDLLHookProc, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Overloads Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Private Overloads Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
    End Function

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure KBDLLHOOKSTRUCT
        Public vkCode As UInt32
        Public scanCode As UInt32
        Public flags As KBDLLHOOKSTRUCTFlags
        Public time As UInt32
        Public dwExtraInfo As UIntPtr
    End Structure

    <Flags()> _
    Private Enum KBDLLHOOKSTRUCTFlags As UInt32
        LLKHF_EXTENDED = &H1
        LLKHF_INJECTED = &H10
        LLKHF_ALTDOWN = &H20
        LLKHF_UP = &H80
    End Enum

    Public Shared Event KeyDown(ByVal Key As Keys)
    Public Shared Event KeyUp(ByVal Key As Keys)

    Private Const WH_KEYBOARD_LL As Integer = 13
    Private Const HC_ACTION As Integer = 0
    Private Const WM_KEYDOWN = &H100
    Private Const WM_KEYUP = &H101
    Private Const WM_SYSKEYDOWN = &H104
    Private Const WM_SYSKEYUP = &H105

    Private Delegate Function KBDLLHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer

    Private KBDLLHookProcDelegate As KBDLLHookProc = New KBDLLHookProc(AddressOf KeyboardProc)
    Private HHookID As IntPtr = IntPtr.Zero

    Private Function KeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        If (nCode = HC_ACTION) Then
            Dim struct As KBDLLHOOKSTRUCT
            Select Case wParam
                Case WM_KEYDOWN, WM_SYSKEYDOWN
                    RaiseEvent KeyDown(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys))
                Case WM_KEYUP, WM_SYSKEYUP
                    RaiseEvent KeyUp(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys))
            End Select
        End If
        Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
    End Function

    Public Sub New()
        HHookID = SetWindowsHookEx(WH_KEYBOARD_LL, KBDLLHookProcDelegate, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
        If HHookID = IntPtr.Zero Then
            Throw New Exception("Could not set keyboard hook")
        End If
    End Sub

    Protected Overrides Sub Finalize()
        If Not HHookID = IntPtr.Zero Then
            UnhookWindowsHookEx(HHookID)
        End If
        MyBase.Finalize()
    End Sub

End Class

With Windbg appeared this code(only the error part):

(17cc.1810): CLR exception - code e0434352 (first chance)
(17cc.1810): Unknown exception - code c000041d (!!! second chance !!!)
eax=0118ed58 ebx=00000005 ecx=00000005 edx=00000000 esi=0118ee24 edi=00000001
eip=77504b32 esp=0118ed58 ebp=0118edb4 iopl=0         nv up ei pl nz ac po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000212
KERNELBASE!RaiseException+0x6c:
77504b32 8b4c2454        mov     ecx,dword ptr [esp+54h] ss:002b:0118edac=d57192f5
*** WARNING: Unable to verify checksum for C:\windows\assembly\NativeImages_v4.0.30319_32\System\f0602360211041a6be208f0b4138dddd\System.ni.dll
*** WARNING: Unable to verify checksum for C:\windows\assembly\NativeImages_v4.0.30319_32\Microsoft.V9921e851#\544c2dc6a8eccbe94917fa495786d228\Microsoft.VisualBasic.ni.dll
*** WARNING: Unable to verify checksum for C:\windows\assembly\NativeImages_v4.0.30319_32\System.Windows.Forms\11b4af16e791a6b0ada4a97d3e64e27a\System.Windows.Forms.ni.dll
0:000> gn
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00000002 edi=0143a8f8
eip=77e2f6b4 esp=054af7f8 ebp=054af990 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
ntdll!NtWaitForWorkViaWorkerFactory+0xc:
77e2f6b4 c21000          ret     10h

No correct solution

OTHER TIPS

These are two distinct errors, what they have in common is sloppy error handling that turns them from common mishaps into mysterious and undiagnosable crashes.

The keyboard hook code you found on the web page has very sloppy handling of winapi errors, throwing a plain Exception with a "could not do it" error message. Very unhelpful of course. You made it worse by not writing code to deal with the possibility that setting the hook can fail, it in turn made the constructor of your Form class fail.

The DllImport declaration for SetWindowsHookEx() is borken, it is missing the SetLastError property. Required to tell .NET that this is a winapi function that reports an error code through Marshal.GetLastWin32Error(). Without this property, there is no way to find out why the function failed. Instead of throwing Exception, it should throw a System.ComponentModel.Win32Exception. Which now contains a decent description of why the function failed. You of course need to catch this exception and display it, then terminate your program since there is no reason to continue running. Use Environment.Exit(). I don't want to guess at the reason for the failure, except that it is uses an outdated way to pass the module handle, the 3rd argument, that is no longer reliable on .NET 4.0 and up. Instead, pinvoke LoadLibrary("user32.dll") to get a usable module handle.

The second crash is a plain "file not found" exception, caused by the Play() method not being able to find the .wav file. Simply forgetting to copy the .wav file is enough to make your program crash like this.

Very common mishap of course, you never want such a plain accident cause your program to fail in such an undiagnosable way. You must write an event handler for the AppDomain.CurrentDomain.UnhandledException event which logs or displays the e.ExceptionObject.ToString() value, then terminate your program. That gives you a decent exception message and the holy stack trace to show you where and why the program failed. Use the Application.Startup event to subscribe the event.

A program isn't truly tested and ready to ship until you've also tested the exceptional ways in which it can behave. Hard to do and often skipped. You need to use a "what if" scenario, intentionally throwing an exception to exercise it is a good way to see if your program can still recover gracefully. Exactly where to put such a throw statement is something that requires experience, the kind you get by troubleshooting failures just like this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top