Reg-Free 进程外 COM 服务器事件
Reg-Free Out-of-process COM server events
我们正在尝试将进程内 COM 对象更改为进程外 COM 对象。新进程只是将 Dispatch 传递给以前使用的 COM 对象,因此我们可以选择返回到进程内对象。
这工作正常,但我们遇到了有关事件的问题。进程外服务器拦截先前使用的 COM 对象的事件,并将这些事件传递给自己的事件接口,该接口也在工作。但问题是,当进程外服务器未在 windows 注册表中注册时,客户端无法使用 DispEventAdvise 连接到此事件接口。
服务器 IDL 如下所示:
[
object,
uuid(www),
dual,
oleautomation,
nonextensible,
helpstring("IControl Interface"),
pointer_default(unique)
]
interface IControl : IDispatch
{
[id(1)] HRESULT CreateDispatch([out] IDispatch** ppDispatch);
};
[
uuid(xxx),
version(1.0),
helpstring("Control Type Library")
]
library ControlLib
{
importlib("stdole2.tlb");
[
uuid(yyy),
helpstring("IControlEvents Interface"),
nonextensible
]
interface IControlEvents : IUnknown
{
[id(1)] HRESULT MyEvent(void);
};
[
uuid(zzz),
helpstring("_IControlEvents Interface")
]
dispinterface _IControlEvents
{
interface IControlEvents;
};
coclass Control
{
[default] interface IControl;
[default, source] dispinterface _IControlEvents;
};
};
我们向客户端和服务器添加了 control_i.c、control_p.c 和 dlldata.c。并且都执行以下步骤来注册 proxy/stub.
PrxDllGetClassObject(IID_IControl, IID_IUnknown, (void **)&punk);
CoRegisterClassObject(IID_IControl, punk, CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &dwRCO);
CoRegisterPSClsid(IID_IControl, IID_IControl);
CoRegisterPSClsid(IID_IControlEvents, IID_IControl);
CoRegisterPSClsid(DIID__IControlEvents, IID_IControl);
这适用于要使用 CoCreateInstance 创建的控件,但不适用于事件。 DispEventAdvise 不断返回 CONNECT_E_CANNOTCONNECT 导致接收器 returns E_NOINTERFACE.
上 DIID__IControlEvents 的 QueryInterface
我们确实需要在不在注册表中注册控件的情况下使它正常工作。我们还尝试使用清单文件和单独的 proxy/stub DLL 来注册它,但没有成功。
我们最终只在注册表中注册了调度事件接口,以便正确注册存根 class。现在是 "registered" 但没有任何文件引用。所以我们仍然可以并排安装。
我们正在尝试将进程内 COM 对象更改为进程外 COM 对象。新进程只是将 Dispatch 传递给以前使用的 COM 对象,因此我们可以选择返回到进程内对象。 这工作正常,但我们遇到了有关事件的问题。进程外服务器拦截先前使用的 COM 对象的事件,并将这些事件传递给自己的事件接口,该接口也在工作。但问题是,当进程外服务器未在 windows 注册表中注册时,客户端无法使用 DispEventAdvise 连接到此事件接口。
服务器 IDL 如下所示:
[
object,
uuid(www),
dual,
oleautomation,
nonextensible,
helpstring("IControl Interface"),
pointer_default(unique)
]
interface IControl : IDispatch
{
[id(1)] HRESULT CreateDispatch([out] IDispatch** ppDispatch);
};
[
uuid(xxx),
version(1.0),
helpstring("Control Type Library")
]
library ControlLib
{
importlib("stdole2.tlb");
[
uuid(yyy),
helpstring("IControlEvents Interface"),
nonextensible
]
interface IControlEvents : IUnknown
{
[id(1)] HRESULT MyEvent(void);
};
[
uuid(zzz),
helpstring("_IControlEvents Interface")
]
dispinterface _IControlEvents
{
interface IControlEvents;
};
coclass Control
{
[default] interface IControl;
[default, source] dispinterface _IControlEvents;
};
};
我们向客户端和服务器添加了 control_i.c、control_p.c 和 dlldata.c。并且都执行以下步骤来注册 proxy/stub.
PrxDllGetClassObject(IID_IControl, IID_IUnknown, (void **)&punk);
CoRegisterClassObject(IID_IControl, punk, CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &dwRCO);
CoRegisterPSClsid(IID_IControl, IID_IControl);
CoRegisterPSClsid(IID_IControlEvents, IID_IControl);
CoRegisterPSClsid(DIID__IControlEvents, IID_IControl);
这适用于要使用 CoCreateInstance 创建的控件,但不适用于事件。 DispEventAdvise 不断返回 CONNECT_E_CANNOTCONNECT 导致接收器 returns E_NOINTERFACE.
上 DIID__IControlEvents 的 QueryInterface我们确实需要在不在注册表中注册控件的情况下使它正常工作。我们还尝试使用清单文件和单独的 proxy/stub DLL 来注册它,但没有成功。
我们最终只在注册表中注册了调度事件接口,以便正确注册存根 class。现在是 "registered" 但没有任何文件引用。所以我们仍然可以并排安装。