gmamaladze / globalmousekeyhook

This library allows you to tap keyboard and mouse, detect and record their activity even when an application is inactive and runs in background.
MIT License
1.05k stars 257 forks source link

Uncomplete release of unmanaged memory? #116

Open juicehifi opened 4 years ago

juicehifi commented 4 years ago

I have experienced problems with unmanaged callbacks to garbage collected instances. I am using the hook in a dll with a GUI - and the problem happened after the object in my dll was brought back during the same session as it had been disposed.

I am using the globalhook like this:

private void SetClearHook(bool _set) { lock (hookLocker) { if (m_Global_Hook != null) { m_Global_Hook.MouseWheel -= Global_Hook_MouseWheel; m_Global_Hook.Dispose(); m_Global_Hook = null; } if (_set) { m_Global_Hook = Hook.GlobalEvents(); m_Global_Hook.MouseWheel += Global_Hook_MouseWheel; } } }

I am using a "local" mouse event to turn the globalhook on - and global moves to turn them off. It seems to me like the mouse events aren't triggered every time, so there's a risk of creating event replicas unless the events are removed and added on the same event.

The above procedure seemed to work 100% the first time the dll was instatiated. Then it failed.

In order to fix this I added base.dispose() to the ReleaseHandle() override in hookprocedurehandle.cs. Here's the modified ReleaseHandle:

    protected override bool ReleaseHandle()
    {
        //NOTE Calling Unhook during processexit causes deley
        //if (!_closing)
        int ret = HookNativeMethods.UnhookWindowsHookEx(handle);
        if (ret != 0)
        {
            base.Dispose();
            return true;
        }
        else
            return true;
    }

So far the problem seems to have disappeared, but I really don't see the whole picture here. It would be nice if you could look into it.

PS thanks for sharing a great piece of code!

richo-tri commented 3 years ago

The above fix also worked for an issue I faced. My issue was somewhat sporadic to reproduce, but it happened enough to be annoying. After trying out the above changes to the ReleaseHandle() method, the issue doesn't seem to be reproducible anymore.

The issue seemed to happen when hooking/unhooking at a frequent basis (once per second or so) The application would receive a null reference exception, without a stacktrace, however, the call stack showed

Gma.System.MouseKeyHook.dll!Gma.System.MouseKeyHook.WinApi.HookHelper.CallNextHookEx(int nCode, System.IntPtr wParam, System.IntPtr lParam)
Gma.System.MouseKeyHook.dll!Gma.System.MouseKeyHook.WinApi.HookHelper.HookProcedure(int nCode, System.IntPtr wParam, System.IntPtr lParam, Gma.System.MouseKeyHook.Implementation.Callback callback)
Gma.System.MouseKeyHook.dll!Gma.System.MouseKeyHook.WinApi.HookHelper.HookGlobal.AnonymousMethod__3(int code, System.IntPtr param, System.IntPtr lParam)

which was happening on the UI thread. So my assumption was that previous handles could potentially not have been disposed properly.