gpt4 book ai didi

c# - 尝试挂接键盘时出现 "CallbackOnCollectedDelegate was detected"

转载 作者:行者123 更新时间:2023-11-30 17:54:13 26 4
gpt4 key购买 nike

我正在使用此代码 GlobalKeyboardHook.cs钩住键盘。

我已经按照 this post 中的说明更改了所有指定内容.现在我的代码如下所示:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Utilities
{
/// <summary>
/// A class that manages a global low level keyboard hook
/// </summary>
class globalKeyboardHook
{
#region Constant, Structure and Delegate Definitions
/// <summary>
/// defines the callback type for the hook
/// </summary>
public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);

public struct keyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}

const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYDOWN = 0x104;
const int WM_SYSKEYUP = 0x105;

private static keyboardHookProc callbackDelegate;

#endregion

#region Instance Variables
/// <summary>
/// The collections of keys to watch for
/// </summary>
public List<Keys> HookedKeys = new List<Keys>();
/// <summary>
/// Handle to the hook, need this to unhook and call the next hook
/// </summary>
IntPtr hhook = IntPtr.Zero;
#endregion

#region Events
/// <summary>
/// Occurs when one of the hooked keys is pressed
/// </summary>
public event KeyEventHandler KeyDown;
/// <summary>
/// Occurs when one of the hooked keys is released
/// </summary>
public event KeyEventHandler KeyUp;
#endregion

#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
/// </summary>
public globalKeyboardHook()
{
hook();
}

/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
/// </summary>
~globalKeyboardHook()
{
unhook();
}
#endregion

#region Public Methods
/// <summary>
/// Installs the global hook
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
callbackDelegate = new keyboardHookProc(hookProc);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0);
if (hhook == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
}

/// <summary>
/// Uninstalls the global hook
/// </summary>
public void unhook()
{
bool ok = UnhookWindowsHookEx(hhook);
if (!ok) throw new System.ComponentModel.Win32Exception();
callbackDelegate = null;
}

/// <summary>
/// The callback for the keyboard hook
/// </summary>
/// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
/// <param name="wParam">The event type</param>
/// <param name="lParam">The keyhook event information</param>
/// <returns></returns>
public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
{
if (code >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key))
{
KeyEventArgs kea = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
{
KeyDown(this, kea);
}
else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
{
KeyUp(this, kea);
}
if (kea.Handled)
return 1;
}
}
return CallNextHookEx(hhook, code, wParam, ref lParam);
}
#endregion

#region DLL imports
/// <summary>
/// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
/// </summary>
/// <param name="idHook">The id of the event you want to hook</param>
/// <param name="callback">The callback.</param>
/// <param name="hInstance">The handle you want to attach the event to, can be null</param>
/// <param name="threadId">The thread you want to attach the event to, can be null</param>
/// <returns>a handle to the desired hook</returns>
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);

/// <summary>
/// Unhooks the windows hook.
/// </summary>
/// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
/// <returns>True if successful, false otherwise</returns>
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);

/// <summary>
/// Calls the next hook.
/// </summary>
/// <param name="idHook">The hook id</param>
/// <param name="nCode">The hook code</param>
/// <param name="wParam">The wparam.</param>
/// <param name="lParam">The lparam.</param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);

/// <summary>
/// Loads the library.
/// </summary>
/// <param name="lpFileName">Name of the library</param>
/// <returns>A handle to the library</returns>
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
#endregion
}
}

当我的程序窗口可见时,我程序中的这个函数会 Hook 向上和向下键。当可见性发生变化时,它会解开这些键。

private void AutoCompleteMenu_VisibleChanged(object sender, EventArgs e)
{
if (this.Visible == true)
{
if (hookFlag == 0)
{
try
{
gkh.hook();
gkh.HookedKeys.Add(Keys.Up);
gkh.HookedKeys.Add(Keys.Down);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
}
catch (Exception)
{
MessageBox.Show("Cannot hook arrow keys! Please use mouse keys to select a word");
}
hookFlag = 1;
}
}
else
{
if (hookFlag == 1)
{
hookFlag = 0;
gkh.unhook();
}
}
}

这段代码写在程序初始化部分:globalKeyboardHook gkh = new globalKeyboardHook();

每当我的程序尝试 Hook 键时,我仍然会收到此错误:

CallbackOnCollectedDelegate was detected Message: A callback was made on a garbage collected delegate of type 'CaretPosition!Utilities.globalKeyboardHook+keyboardHookProc::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.

请帮我解决这个问题。

最佳答案

可能会发生,垃圾收集根本不会发生,当您关闭应用程序时,它会导致 Hook 无效委托(delegate)(因为应用程序已卸载)。

您不应该使用终结器 ~globalKeyboardHook 来释放除已分配内存以外的系统资源,而应该使用 IDisposable 并显式解钩。或者你可以解开

AppDomain.CurrentDomain.ProcessExit

事件

关于c# - 尝试挂接键盘时出现 "CallbackOnCollectedDelegate was detected",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16295289/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com