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

时间:2009-10-28 16:25:35

标签: c# .net events com vb6

我在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服务器作为控件添加到工具箱中。

4 个答案:

答案 0 :(得分:1)

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

我回过头来看看我做了什么,唯一的区别是我可以看到委托定义在我的COM类中,我也看到在example中发生。

所以尝试在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);
    }

答案 1 :(得分:1)

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

显然UserControl实现了一些使这个工作正常的接口......谁知道......

答案 2 :(得分:0)

您可能忘了添加 [集会:Guid(" ......")] 到您的项目,这意味着每次重新编译C#项目时,COM中的TypeLib ID都会更改。

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

答案 3 :(得分:0)

我找到了针对此问题的修复程序,该修复程序使我可以使用从Control(而不是UserControl)继承的自定义控件。

在代码编辑器中,为WithEvents变量添加一个声明:

Dim WithEvents ControlNameEvents As ControlLibrary.ControlName

在Form_Load事件处理程序中,添加以下代码以初始化WithEvents变量:

Private Sub Form_Load()
    Set ControlNameEvents = Me.ControlNameOnVB6Form
End Sub

添加代码以在WithEvents变量的事件处理程序中处理您的自定义事件:

Private Sub ControlNameEvents_MyCustomEvent()
    MsgBox("My custom event fired")
End Sub

来源:http://froque.github.io/VSIXInteropFormsToolkit/How%20To/Interop%20User%20Control%20Events.html