C# – 编写COM服务器 – 未在客户端上触发的事件

我在C#中实现了一个COM服务器,它有一个vb6客户端。

当我要触发我的事件时,处理程序总是为空 – 看来vb6应用程序从不订阅我的事件。

vb6应用程序是现有的第三方应用程序,似乎没有提供任何错误消息。

普通方法可以在COM客户端 – >服务器上正常工作。

我可以做些什么来调试正在发生的事情? 或者为什么我的活动不起作用?

以下是我的代码的快速示例代码段:

[ComVisible(true), Guid(Constants.CLASS_IID), ProgId(Constants.PROG_ID), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IMyServiceEvents))] public class MyClass : Control, IMyService, IMyServiceEvents { [DispId(1)] public event MyEventHandler MyEvent; //... also implements IMyService, which is working } [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch), Guid(Constants.EVENTS_IID)] public interface IMyServiceEvents { [PreserveSig, DispId(1)] void MyEvent([In]int Status); } [ComVisible(false)] public delegate void MyEventHandler(int Status); 

如果我尝试使用我的C#com服务器替换/实现的现有ocx文件,事件将照常工作。 它也是用vb6编写的,所以我的C#服务器中的东西一定是错的。

我还想补充一点,我尝试了ClassInterfaceType的所有3个设置,并得到了相同的结果 – 虽然我不得不为每次尝试重新注册我的COM服务器。

看看我生成的IDL,它看起来对我来说是正确的,并且一切看起来都非常类似于我正在尝试重新创建的原始IDL,如果需要,我可以发布。

更新:嗯,我拿出旧的Visual Studio 6,并制作了一个VB6应用程序来测试我的C#COM服务器,它工作正常。

所以我采用了一个免费的vb6反编译程序,它可以将反编译的代码输出到vb6项目,然后在我想要加载我的COM服务器的第三方应用程序上运行它 – 并且看到它不起作用。

我注意到他们的应用程序使用我的COM服务器作为设计器的控件,我的测试程序只是在表单中声明了一个成员变量WithEvents。 幕后是否有一些与设计师有关的事情正在破坏这一点? 如何使我的COM服务器ActiveX兼容? 我还注意到VB6 ide不允许我将C#com服务器作为控件添加到工具箱中。

我依稀记得自己有这个错误,就像运行时不知道如何将COM注册映射到你的事件。

我回过头来看看我做了什么,唯一的区别是我可以看到委托定义在我的COM类中,我也看到在这个例子中出现 。

因此,尝试在MyClass中移动MyEventHandler,如下所示:

  [ComVisible(true), Guid(Constants.CLASS_IID), ProgId(Constants.PROG_ID), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IMyServiceEvents))] public class MyClass : Control, IMyService, IMyServiceEvents { [ComVisible(false)] public delegate void MyEventHandler(int Status); [DispId(1)] public event MyEventHandler MyEvent; //... also implements IMyService, which is working } [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch), Guid(Constants.EVENTS_IID)] public interface IMyServiceEvents { [PreserveSig, DispId(1)] void MyEvent([In]int Status); } 

我是从Control派生出来的,而不是UserControl,我看到了一个在C#中实现ActiveX控件的例子。

显然UserControl实现了一些使这个工作正常的界面…谁知道……

您可能忘记将[assembly:Guid(“…”)]添加到项目中,这意味着每次重新编译C#项目时,COM中的TypeLib ID都会更改。

如果没有该属性,编译器将生成不同的类型库,但某些COM函数在没有匹配库ID的情况下工作。