我正在使用this sample作为我正在制作的计划的基础。大约618次击键后,程序抛出此错误:
CallbackOnCollectedDelegate was detected
Message: A callback was made on a garbage collected delegate of type 'KeyLogger!KeyLogger.CallBackFunction+DelegateCallBack::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.
运行应用程序时大多数时间都会抛出错误,但不是每次都会抛出错误,而不是同一个按键次数。从错误消息,我认为这听起来像垃圾收集器正在收集委托,我该如何防止这种情况?
我制作的程序本质上是该vb.net项目的修改版本,但它实际上并不存储击键。
感谢您的帮助!
CallBack.vb中的代码:
Option Strict Off
Option Explicit On
Module CallBackFunction
'******************************************************************************************
' Sample for retrieving keystrokes by use of the "kbLog32.dll"
' (c) 2004 by Nadeem Afanah.
'******************************************************************************************
'CallBack function
Delegate Sub DelegateCallBack(ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer)
Sub CallBack(ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer)
'here we track only WM_CHAR and WM_KEYDOWN
If msg = WM_KEYDOWN Then
...
End If
End Sub
End Module
Declarations.vb中的代码:
Option Strict Off
Option Explicit On
Module Declarations
'******************************************************************************************
' Sample for retrieving keystrokes by use of the "kbLog32.dll"
' (c) 2004 by Nadeem Afanah.
'******************************************************************************************
'******************************************************************************************
'DLL declarations
Public Declare Function StartLog Lib "kbLog32" (ByVal hWnd As Integer, ByVal lpFuncAddress As DelegateCallBack) As Integer
Public Declare Sub EndLog Lib "kbLog32" ()
'----------------------------------------------------------------------------------------
Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Integer, ByVal hWndInsertAfter As Integer, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As Integer) As Integer
Declare Function FindWindow Lib "user32" Alias "FindWindowA"(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA"(ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer
'****************************************************************************************
' Keyboard messages
Public Const WM_KEYUP As Short = &H101s
Public Const WM_KEYDOWN As Short = &H100s
Public Const WM_CHAR As Short = &H102s
Public Const WM_SYSKEYDOWN As Short = &H104s
Public Const WM_SYSKEYUP As Short = &H105s
'SetWindowPos messages
Public Const SWP_NOSIZE As Short = &H1s
Public Const SWP_NOMOVE As Short = &H2s
Public Const HWND_TOPMOST As Short = -1
Public Const SWP_SHOWWINDOW As Short = &H40s
'******************************************************************************************
End Module
答案 0 :(得分:3)
查看Form1.vb中的代码,它执行此操作:
StartLog(nhWnd_text, AddressOf CallBack)
这就是它所说的,把Callback函数的位置用来处理我收到的关于键盘事件的消息。
尝试这样的事情:
Friend Class Form1
Inherits System.Windows.Forms.Form
''Add this ----------------------------
<MarshalAs(UnmanagedType.FunctionPtr)> _
Private DelSub as New DelegateCallBack(AdressOf CallBack)
''-------------------------------------
''In the sub Sub Command1_Click
''Change this -------------------------
StartLog(nhWnd_text, AddressOf CallBack)
''To this -----------------------------
StartLog(nhWnd_text, DelSub)
''-------------------------------------
End Class
我们在这里做的是创建一个本地“委托子”(将其视为指向子的变量)。我们将此指向Callback
子。然后我们使用这个委托子,而不是直接将引用传递给Callback
sub。
区别在于.Net框架现在知道有一些东西指向那个sub,所以不会垃圾收集它(从内存中清除它)
MarshallAs位有点多余,因为它是默认的编组,但它只是意味着我们明确地告诉.Net我们正在使用委托来访问非托管代码(在.Net框架之外的东西)
仅仅是为了记录,我仍然需要下载代码,因为它实际上是相关的Form1.vb中的位 - 但感谢您的尝试:)