注册C++;带有C#COM服务器的接收器 我想注册一个带有Exchange接口的C++接收器,因此登记一个C应用程序的事件。
C#应用程序是Outlook的外接程序,充当COM服务器,支持传入和传出接口。该服务器的客户端是包含下沉的C++应用程序,我也在开发。p> 我通过注册运行对象表上的ADIN(RoT),从C++应用程序中的Road检索指针,然后调用传入接口的方法,来获得COM服务器(ADIN)的传入接口。p>注册C++;带有C#COM服务器的接收器 我想注册一个带有Exchange接口的C++接收器,因此登记一个C应用程序的事件。,c#,c++,outlook,com,interop,C#,C++,Outlook,Com,Interop,C#应用程序是Outlook的外接程序,充当COM服务器,支持传入和传出接口。该服务器的客户端是包含下沉的C++应用程序,我也在开发。p> 我通过注册运行对象表上的ADIN(RoT),从C++应用程序中的Road检索指针,然后调用传入接口的方法,来获得COM服务器(ADIN)的传入接口。p> 当试图将C++接收器登记到AdIn的相关接口的ICONNECTURE点时,问题发生。p> 以下缩减代码显示了我的加载项(C#COM服务器): 接口MyInterface和_IEvents的.idl如下所示:
当试图将C++接收器登记到AdIn的相关接口的ICONNECTURE点时,问题发生。p> 以下缩减代码显示了我的加载项(C#COM服务器):
接口MyInterface和_IEvents的.idl如下所示:import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
dual,
pointer_default(unique)
]
interface IComponentRegistrar : IDispatch
{
[id(1)] HRESULT Attach([in] BSTR bstrPath);
[id(2)] HRESULT RegisterAll();
[id(3)] HRESULT UnregisterAll();
[id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
[id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID);
[id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
};
[
object,
uuid(6C032E68-4DF7-49BE-9949-88F8AADD3D40),
dual,
nonextensible,
pointer_default(unique)
]
interface IMyInterface : IDispatch
{
[id(1)] void IncomingInterfaceMethod();
};
[
uuid(D3E30009-BF30-4BFD-BF4D-88306D90CA0F),
version(1.0),
custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{43B9624D-0143-438F-A5B1-7CC09F733476}")
]
library MyComLib
{
importlib("stdole2.tlb");
[
uuid(43B9624D-0143-438F-A5B1-7CC09F733476)
]
coclass CompReg
{
[default] interface IComponentRegistrar;
};
[
uuid(D2A0BE8B-BB05-4472-9976-D17AD5EBDABD)
]
dispinterface _IEvents
{
properties:
methods:
[id(1)] void Event1();
};
[
uuid(76ED50BC-5DE0-43DA-83FA-5CD44E88B481)
]
coclass MyInterface
{
[default] interface IMyInterface;
[default, source] dispinterface _IEvents;
};
};
这在ATL项目中定义,并内置到.dll中并注册。这将在addin C#项目中引用
最后,C++ APP接收器头看起来像这样:
class MySink : public _IEvents
{
public:
...
STDMETHOD_(ULONG, AddRef)()
{
InterlockedIncrement(&m_refCount);
return m_refCount;
}
STDMETHOD_(ULONG, Release)()
{
InterlockedDecrement(&m_refCount);
if (m_refCount == 0)
{
delete this;
return 0;
}
return m_refCount;
}
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject)
{
if (riid == IID_IUnknown)
{
*ppvObject = (IUnknown*)this;
AddRef();
return S_OK;
}
if ((riid == IID_IDispatch) || (riid == __uuidof(_IEvents)))
{
*ppvObject = (IDispatch*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHOD(GetTypeInfoCount)(UINT* /*pctinfo*/)
{
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo)(UINT /*itinfo*/, LCID /*lcid*/, ITypeInfo** /*pptinfo*/)
{
return E_NOTIMPL;
}
STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR* /*rgszNames*/, UINT /*cNames*/, LCID /*lcid*/, DISPID* /*rgdispid*/)
{
return E_NOTIMPL;
}
STDMETHOD(Invoke)(
DISPID dispidMember,
REFIID /*riid*/,
LCID /*lcid*/,
WORD /*wFlags*/,
DISPPARAMS* pdispparams,
VARIANT* /*pvarResult*/,
EXCEPINFO* /*pexcepinfo*/,
UINT* /*puArgErr*/)
{
return m_eventCB(dispidMember, pdispparams);
}
bool SetupConnectionPoint(IMyInterface* myInterface);
private:
bool CheckResult(HRESULT hr, std::wstring errMsg);
ULONG m_refCount;
EventCB m_eventCB;
DWORD m_eventCookie = 0u;
IConnectionPoint* m_connectionPoint = nullptr;
IUnknown* m_ftm = nullptr;
};
以下是MySink的来源:
...
// myInterface is retrieved from ROT and then passed here
bool MySink::SetupConnectionPoint(IMyInterface* myInterface)
{
// Don't know if this is necessary
CoCreateFreeThreadedMarshaler(this, &m_ftm);
HRESULT hr;
IConnectionPointContainer* pIConnectionPointContainerTemp = nullptr;
hr = myInterface->QueryInterface(IID_IConnectionPointContainer, (void**)&pIConnectionPointContainerTemp);
if (!CheckResult(hr, L"Failed to retrieve ConnectionPointContainer") || !pIConnectionPointContainerTemp)
{
return false;
}
pIConnectionPointContainerTemp->FindConnectionPoint(__uuidof(_IEvents), &m_connectionPoint);
pIConnectionPointContainerTemp->Release();
pIConnectionPointContainerTemp = nullptr;
if (m_connectionPoint)
{
m_connectionPoint->Advise(this, &m_eventCookie);
}
else
{
return false;
}
return true;
}
bool MySink::CheckResult(HRESULT hr, std::wstring errMsg)
{
if (FAILED(hr))
{
// Used for logging
_com_error comError(hr);
return false;
}
return true;
}
MySink::SetupConnection()似乎正在使用填充的m_connectionPoint和对其调用的Advise()。在调试ADIN和调用C++应用程序中的InCopyTrimeMeMeDoEd()时,EVET1仍然是NULL,因此不被调用。我猜MySink和加载项之间的注册工作不正常,因此Event1始终为空。运行时可调用包装器可能有问题
<>我必须重构代码,因此可能有命名错误。您可以考虑实现ATL或在客户端中,而不是创建自己的接收器。查看教程中的示例。感谢有用的教程
...
// myInterface is retrieved from ROT and then passed here
bool MySink::SetupConnectionPoint(IMyInterface* myInterface)
{
// Don't know if this is necessary
CoCreateFreeThreadedMarshaler(this, &m_ftm);
HRESULT hr;
IConnectionPointContainer* pIConnectionPointContainerTemp = nullptr;
hr = myInterface->QueryInterface(IID_IConnectionPointContainer, (void**)&pIConnectionPointContainerTemp);
if (!CheckResult(hr, L"Failed to retrieve ConnectionPointContainer") || !pIConnectionPointContainerTemp)
{
return false;
}
pIConnectionPointContainerTemp->FindConnectionPoint(__uuidof(_IEvents), &m_connectionPoint);
pIConnectionPointContainerTemp->Release();
pIConnectionPointContainerTemp = nullptr;
if (m_connectionPoint)
{
m_connectionPoint->Advise(this, &m_eventCookie);
}
else
{
return false;
}
return true;
}
bool MySink::CheckResult(HRESULT hr, std::wstring errMsg)
{
if (FAILED(hr))
{
// Used for logging
_com_error comError(hr);
return false;
}
return true;
}