Приложение1 перестало работать

Я разработал программу, которая содержит клавиатуру (находится на этой веб-странице) и воспроизводит звук, когда пользователь нажимает клавишу.

Когда я отлаживаю его, он работает отлично, но иногда появляется эта ошибка:

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: )

Но когда я его публикую, выполняю и нажимаю клавишу, эта ошибка всегда появляется:

"Приложение1 перестало работать, Windows собирает дополнительную информацию о проблеме..."

Я не знаю почему.

Как я могу это исправить?

в WER (сообщение об ошибке Windows), это появляется (это на испанском, потому что я испанский)

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

В форме 1 у меня есть этот код:

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

И это код из Интернета:

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

С Windbg появился этот код (только часть ошибки):

(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

1 ответ

Это две разные ошибки, их объединяет неаккуратная обработка ошибок, которая превращает их из общих неудач в таинственные и не диагностируемые сбои.

Код хука клавиатуры, который вы нашли на веб-странице, очень неаккуратно обрабатывает ошибки winapi, создавая простое исключение с сообщением об ошибке "не удалось". Очень бесполезно, конечно. Вы усугубили ситуацию, не написав код, чтобы учесть вероятность того, что установка хука может не сработать, а это в свою очередь привело к сбою конструктора вашего класса Form.

Объявление DllImport для SetWindowsHookEx() является borken, в нем отсутствует свойство SetLastError. Требуется сообщить.NET, что это функция winapi, которая сообщает код ошибки через Marshal.GetLastWin32Error(). Без этого свойства невозможно найти причину сбоя функции. Вместо того, чтобы генерировать Exception, он должен генерировать System.ComponentModel.Win32Exception. Который теперь содержит приличное описание того, почему функция не сработала. Вам, конечно, нужно перехватить это исключение и отобразить его, а затем прекратить работу программы, поскольку нет причин продолжать работу. Используйте Environment.Exit(). Я не хочу догадываться о причине сбоя, за исключением того, что он использует устаревший способ передачи дескриптора модуля, 3-й аргумент, который больше не является надежным в.NET 4.0 и выше. Вместо этого, введите команду LoadLibrary("user32.dll"), чтобы получить доступный дескриптор модуля.

Второй сбой представляет собой простое исключение "файл не найден", вызванный тем, что метод Play() не может найти файл.wav. Достаточно просто забыть скопировать файл.wav, чтобы ваша программа вылетала вот так.

Конечно, это очень частая неудача, вы никогда не хотите, чтобы такая простая авария приводила к сбою вашей программы таким неописуемым образом. Вы должны написать обработчик события для события AppDomain.CurrentDomain.UnhandledException, который регистрирует или отображает значение e.ExceptionObject.ToString(), а затем завершает свою программу. Это дает вам достойное сообщение об исключении и трассировку святого стека, чтобы показать вам, где и почему произошла ошибка программы. Используйте событие Application.Startup, чтобы подписаться на событие.

Программа по-настоящему не протестирована и не готова к отправке, пока вы не протестируете исключительные способы ее поведения. Трудно сделать и часто пропускается. Вам нужно использовать сценарий "что если", намеренно выбрасывая исключение, чтобы проверить, является ли это хорошим способом проверить, может ли ваша программа все еще корректно восстановиться. Точно, где поместить такой оператор броска, требуется опыт, такой, какой вы получаете, устраняя ошибки, как это.

Другие вопросы по тегам