首页 > 解决方案 > 如何在未注册的 COM 服务器中使用事件

问题描述

对于开发,我使用 EXE 文件中包含的进程外 COM 服务器而不注册它。只要客户端只使用后期绑定,并且我在启动一个客户端之前启动服务器 EXE,这就可以正常工作。(服务器注册一个类工厂,然后由客户端使用。)

我知道这是一个 hack,而且我知道这可能会在任何操作系统组件的下一次更新中停止工作。我这样做只是为了开发,而不是为了测试,绝对不是为了与生产相关的任何事情。

但是,使用事件不起作用:客户端在调用时报告 CONNECT_E_CANNOTCONNECT IConnectionPoint.Advise,即“订阅”事件时。

我怎样才能使这项工作?

一些细节:

  1. 我有一个IFooEventsGUID接口{111blah...},客户端(根据 Procmon)尝试查找HKCR\Interfaces\{111blah...}。如果此密钥存在,它将包含:

    [HKEY_CLASSES_ROOT\Interface\{111blah...}]
    @="IFooEvents"
    
    [HKEY_CLASSES_ROOT\Interface\{111blah...}\ProxyStubClsid32]
    @="{00020420-0000-0000-C000-000000000046}"          <-- PSDispatch?
    
    [HKEY_CLASSES_ROOT\Interface\{111blah...}\TypeLib]
    @="{GUID of the server assembly}"
    "Version"="1.0"
    

    这里有什么相关的?是吗PSDispatch,如果是的话,有没有办法可以在运行时提供这些信息?

我的测试客户端恰好是 .NET,并用于dynamic确保使用后期绑定。

  1. 堆栈跟踪:

    System.Runtime.InteropServices.COMException: 'No such interface supported
    at System.Runtime.InteropServices.ComTypes.IConnectionPoint.Advise(Object pUnkSink, Int32& pdwCookie)
    at System.Dynamic.ComEventSink.Initialize(Object rcw, Guid sourceIid)
    at System.Dynamic.ComEventSink..ctor(Object rcw, Guid sourceIid)
    at System.Dynamic.ComEventSink.FromRuntimeCallableWrapper(Object rcw, Guid sourceIid, Boolean createIfNotFound)
    at System.Dynamic.BoundDispEvent.InPlaceAdd(Object handler)
    at System.Dynamic.BoundDispEvent.TryBinaryOperation(BinaryOperationBinder binder, Object handler, Object& result)
    at CallSite.Target(Closure , CallSite , Object , SomethingHappenedEventHandler )
    at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
    at Program.Main()
    
  2. .NET 框架单步执行失败,VS 报告它找不到Binder.cs,我无法单步执行代码。此外,我在堆栈跟踪中找不到任何代码的来源。

  3. 为了完整起见:注册 COM 服务器 EXE 文件后一切正常。

如果不可能,我很高兴知道原因,只是为了了解更多关于 COM 的信息。

标签: eventscom

解决方案


推荐阅读