在BHO(浏览器助手对象)中使用时,SetWinEventHook会破解IE

时间:2012-08-29 02:09:36

标签: winapi interop internet-explorer-9 com-interop bho

我有一个C#BHO设置一个钩子,以便我可以跟踪IE何时获得焦点:

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)
    {

    }

它工作了一段时间然后IE崩溃“尝试读取或写入受保护的内存。这通常表明其他内存已损坏”

请注意,即使WinEventProc中没有任何内容,它也会崩溃(如上所示)。如果我没有设置钩子,它永远不会崩溃。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您的回调代表可能正在使用GC。而不是使用自动委托创建功能,创建一个显式的,然后将其传递给SetWinEventHook,然后将其保存在实例成员中,直到完成它为止。

代码可能类似于:

// 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);

让成员引用委托使其不被收集。