0

IEがフォーカスを取得したときに追跡できるようにフックを設定するC#BHOがあります。

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に何もない場合でもクラッシュすることに注意してください(上記のように)。フックを設定しないと、クラッシュすることはありません。

何か案は?

4

1 に答える 1

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

デリゲートをメンバーから参照させると、デリゲートが収集されなくなります。

于 2012-08-29T18:12:12.383 に答える