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