I have to implement the ICorDebugManagedCallback interfaces. I wrote up a stub implementation (that just E_NOTIMPLs all the methods) and am posting it here for reference. It's pretty tedious, so I'll post it here and then never have to write that again.

As a language design point, it's definitely annoying using Interfaces for callback here because you have to write a handler for every possible method. It makes the advantage of C#'s Events much more obvious - you can just subscribe to the ones you want. That's a great quality for events that are ignorable (the framework can provide an intelligent default implementation and so your app doesn't need to handle them if it doesn't care).

Mdbg (our managed wrapprs for ICorDebug) converts from interface-based event dispatch to Event subscription dispatch.

When the callback is dispatched, the debuggee is stopped, and you need to continue it. In some cases, if the callback returns E_NOTIMPL, ICorDebug will automatically continue for you; but I don't know how consistently it does that.
So in general, the "empty" implementation of an ICorDebug callbacks has to at least call ICorDebugAppDomain::Continue() and return S_OK.

 

Feel free to copy + paste this at will if you happen to find it useful.


#define COM_METHOD  HRESULT STDMETHODCALLTYPE


class DefaultCallback :
   
public ICorDebugManagedCallback,
   
public ICorDebugManagedCallback2
{
   // Include your favorite implementation of IUnknown here

   
//
    // Implementation of ICorDebugManagedCallback
    //

    COM_METHOD Breakpoint( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugBreakpoint *pBreakpoint)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD StepComplete( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugStepper *pStepper,
        CorDebugStepReason reason)
    {
       
return E_NOTIMPL;
    }
    COM_METHOD Break( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *thread)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD Exception( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        BOOL unhandled)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD EvalComplete( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugEval *pEval)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD EvalException( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugEval *pEval)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD CreateProcess( ICorDebugProcess *pProcess)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD ExitProcess( ICorDebugProcess *pProcess)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD CreateThread( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *thread)
    {
       
return E_NOTIMPL;
    }


    COM_METHOD ExitThread( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *thread)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD LoadModule( ICorDebugAppDomain *pAppDomain,
        ICorDebugModule *pModule)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD UnloadModule( ICorDebugAppDomain *pAppDomain,
        ICorDebugModule *pModule)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD LoadClass( ICorDebugAppDomain *pAppDomain,
        ICorDebugClass *c) 
    {
       
return E_NOTIMPL;
    }

    COM_METHOD UnloadClass( ICorDebugAppDomain *pAppDomain,
        ICorDebugClass *c)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD DebuggerError( ICorDebugProcess *pProcess,
        HRESULT errorHR,
        DWORD errorCode)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD LogMessage( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        LONG lLevel,
        WCHAR *pLogSwitchName,
        WCHAR *pMessage)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD LogSwitch( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        LONG lLevel,
        ULONG ulReason,
        WCHAR *pLogSwitchName,
        WCHAR *pParentName)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD CreateAppDomain( ICorDebugProcess *pProcess,
        ICorDebugAppDomain *pAppDomain)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD ExitAppDomain( ICorDebugProcess *pProcess,
        ICorDebugAppDomain *pAppDomain)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD LoadAssembly( ICorDebugAppDomain *pAppDomain,
        ICorDebugAssembly *pAssembly)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD UnloadAssembly( ICorDebugAppDomain *pAppDomain,
        ICorDebugAssembly *pAssembly)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD ControlCTrap( ICorDebugProcess *pProcess)
    {
       
return E_NOTIMPL;
    }


    COM_METHOD NameChange( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread)
    {
       
return E_NOTIMPL;
    }


    COM_METHOD UpdateModuleSymbols( ICorDebugAppDomain *pAppDomain,
        ICorDebugModule *pModule,
        IStream *pSymbolStream)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD EditAndContinueRemap( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugFunction *pFunction,
        BOOL fAccurate)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD BreakpointSetError( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugBreakpoint *pBreakpoint,
        DWORD dwError)
    {
       
return E_NOTIMPL;
    }

   
///
    /// Implementation of ICorDebugManagedCallback2
    ///

    COM_METHOD FunctionRemapOpportunity( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugFunction *pOldFunction,
        ICorDebugFunction *pNewFunction,
        ULONG32 oldILOffset)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD CreateConnection( ICorDebugProcess *pProcess,
        CONNID dwConnectionId,
        WCHAR *pConnName)
    {
       
return E_NOTIMPL;
    }

    COM_METHOD ChangeConnection( ICorDebugProcess *pProcess,
        CONNID dwConnectionId )
    {
       
return E_NOTIMPL;
    }


    COM_METHOD DestroyConnection( ICorDebugProcess *pProcess,
        CONNID dwConnectionId )
    {
       
return E_NOTIMPL;
    }

    COM_METHOD Exception(  ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugFrame *pFrame,
        ULONG32 nOffset,
        CorDebugExceptionCallbackType dwEventType,
        DWORD dwFlags )
    {
       
return E_NOTIMPL;
    }


    COM_METHOD ExceptionUnwind(  ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        CorDebugExceptionUnwindCallbackType dwEventType,
        DWORD dwFlags )
    {
       
return E_NOTIMPL;
    }

    COM_METHOD FunctionRemapComplete( ICorDebugAppDomain *pAppDomain,
        ICorDebugThread *pThread,
        ICorDebugFunction *pFunction)
    {
       
return E_NOTIMPL;
    }


    COM_METHOD MDANotification(
        ICorDebugController * pController,
        ICorDebugThread *pThread,
        ICorDebugMDA * pMDA
        )
    {
       
return E_NOTIMPL;
    }
};