I have an ATL in-process server that implements a callback interface like so:
.idl
interface IClientEvents : IUnknown{
[] HRESULT TestEvent(void);
};
interface IATLSimpleObject : IDispatch{
[id(1)] HRESULT Advise([in] IClientEvents* clientEvents);
[id(2)] HRESULT Unadvise(void);
};
.h
private:
IClientEvents* m_ClientEvents;
public:
STDMETHOD(Advise)(IClientEvents* clientEvents);
STDMETHOD(Unadvise)(void);
.cpp
STDMETHODIMP CATLSimpleObject::Advise(IClientEvents* clientEvents)
{
m_ClientEvents = clientEvents;
m_ClientEvents->AddRef();
return S_OK;
}
STDMETHODIMP CATLSimpleObject::Unadvise(void)
{
m_ClientEvents->Release();
m_ClientEvents = NULL;
return S_OK;
}
C# client
public partial class Form1 : Form, ATLProject1Lib.IClientEvents
{
private ATLProject1Lib.ATLSimpleObject ATLSimple = new ATLProject1Lib.ATLSimpleObject();
private void Form1_Shown(object sender, EventArgs e)
{
ATLSimple.Advise(this);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
ATLSimple.Unadvise();
}
It works fine, but I need to do exactly the same in an out-of-process server, however, on execution I get an 'Interface not Registered' (80040105) error when calling 'ATLSimple.Advise(this)'.
I've spent hours searching for similar problems, but can't find anything. Any help would be greatly appreciated.
In order for this to work out-of-proc you need the interfaces to be marshalled between processes. Most likely you will want to rely on Automation marshalling which uses a typelib generated from your IDL to find what and how to marshall. The problem is that will only work for interfaces that are marked
[oleautomation]
,[dual]
or both in the IDL. See this answer for more details.You best bet is marking the interfaces you want marshalled as
[oleautomation]
and adding a comment like "Marshalling magic goes away if you remove this".