问题
I have a C# BHO which sets a hook so that I can track when IE gets focus:
public class BHO : IObjectWithSite, IOleCommandTarget
{
delegate void WinEventDelegate(IntPtr hWinEventHook,
uint eventType, IntPtr hwnd, int idObject,
int idChild, uint dwEventThread, uint dwmsEventTime);
const uint WINEVENT_OUTOFCONTEXT = 0;
const uint EVENT_SYSTEM_FOREGROUND = 3;
[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin,
uint eventMax, IntPtr hmodWinEventProc,
WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
private static IntPtr m_hhook;
............
m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND,
EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
............
void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild,
uint dwEventThread, uint dwmsEventTime)
{
}
It works for a while and then IE crashes with "Attempted to read or write protected memory. This is often an indication that other memory is corrupt"
Note that it crashes even when there is nothing in WinEventProc (as shown above). If I don't set the hook, it never crashes.
Any ideas?
回答1:
Your callback delegate might be getting GC'd. Instead of using the automatic delegate creation feature, create an explicit one, pass that to SetWinEventHook, and then keep it around in an instance member until you're done with it.
Code might look something like:
// In the class...
WinEventDelegate m_wineventprocDelegate;
// When you register the hook...
m_wineventprocDelegate = new winEventDelegate(WinEventProc);
// Pass in the delegate instead of WinEventProc
m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND,
EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
m_wineventprocDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);
Having the delegate referenced by a member keeps it from getting collected.
来源:https://stackoverflow.com/questions/12170004/setwineventhook-crahes-ie-when-used-in-bho-browser-helper-object