SetWinEventHook Only Hitting Callback Once Per App

2019-08-29 01:44发布

问题:

I have this class that listens for when the CTRL + ALT + DEL screen is visible. When I run my app it only works one time then the callback is never hit again. Occasionally it appears to cause a memory leak giving me a System.AccessViolationException. I know this Exception is related to this hook because when I remove the hook code it never raises this exceptions.

What am I doing wrong? Why would it only execute the callback once?

public static void StartListeningForDesktopSwitch()
{
    SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH,
        IntPtr.Zero, EventCallback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNTHREAD);
}

public static void EventCallback(IntPtr hWinEventHook, uint eventType,
    IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
    //do stuff when secure desktop is shown or hidden
    Log.LogEvent("Info", "Secure Desktop Event", "", "", null);
}

public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
    IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);


[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
        hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
    uint idThread, uint dwFlags);

const uint WINEVENT_OUTOFCONTEXT = 0x0000;
const uint WINEVENT_SKIPOWNTHREAD = 0x0001;
const uint EVENT_SYSTEM_DESKTOPSWITCH = 0x0020;

I'm calling this static class from Main() like this:

WindowEventHook.StartListeningForDesktopSwitch();

回答1:

How did you use the outside variable?

Try storing the callback in a static variable to keep it from being GCed. Like this:

public static class WindowEventHook
{
    private static readonly WinEventDelegate callback = EventCallback;

    public static void StartListeningForDesktopSwitch()
    {
        SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH,
            IntPtr.Zero, callback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNTHREAD);
    }

    ...
}