我开发了一个包含键盘钩子的程序(在此webpage中),当用户按下某个键时它会播放声音。
当我调试它时,它运行正常,除非有时出现此错误:
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: )
但是当我发布它时,执行它并按一个键,这个错误总是出现:
“Application1已停止工作,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
在form1中我有这段代码:
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
答案 0 :(得分:3)
这是两个截然不同的错误,它们的共同点是草率的错误处理,将它们从常见的灾难转变为神秘和不可诊断的崩溃。
您在网页上找到的键盘钩子代码对winapi错误进行了非常草率的处理,抛出了一个带有“无法做到”错误消息的简单异常。当然非常无益。你通过不编写代码来处理设置钩子可能失败的可能性使情况变得更糟,反过来又使得Form类的构造函数失败。
SetWindowsHookEx()的DllImport声明是borken,它缺少SetLastError属性。需要告诉.NET这是一个通过Marshal.GetLastWin32Error()报告错误代码的winapi函数。如果没有此属性,则无法找出函数失败的原因。它应该抛出System.ComponentModel.Win32Exception而不是抛出异常。现在包含对函数失败原因的正确描述。您当然需要捕获此异常并显示它,然后终止您的程序,因为没有理由继续运行。使用Environment.Exit()。我不想猜测失败的原因,除了它使用过时的方式传递模块句柄,第三个参数,在.NET 4.0及更高版本上不再可靠。相反,请调用LoadLibrary(“user32.dll”)来获取可用的模块句柄。
第二次崩溃是一个普通的“找不到文件”异常,由Play()方法无法找到.wav文件引起。简单地忘记复制.wav文件就足以让你的程序崩溃了。
当然,非常常见的事故,你永远不会想要这样一个简单的事故导致你的程序以这种不可诊断的方式失败。您必须为AppDomain.CurrentDomain.UnhandledException事件编写一个事件处理程序,该事件处理程序记录或显示e.ExceptionObject.ToString()值,然后终止您的程序。这会给你一个体面的异常消息和神圣的堆栈跟踪,以显示程序失败的位置和原因。使用Application.Startup事件来订阅事件。
程序未经过真正测试并准备发货,直到您还测试了它的特殊表现方式。很难做,经常跳过。你需要使用“假设”场景,故意抛出异常来锻炼它是一个好方法,看看你的程序是否仍能优雅地恢复。确切地说,将这样的抛出语句放在何处需要经验,就像通过故障排除故障那样。