com - C# 到 VB6 COM 事件 (“object or class does not support the set of events” ),但不同

标签 com vb6 com-interop

我知道一个 10 年前的问题与这个问题的标题相同,但我已经仔细检查过,我没有错误地使用委托(delegate)人姓名。这是一个不同的问题。

在工作中,我们有一个旧的 VB6 应用程序,我需要教授新的(呃)技巧。我必须做的第一件事是让它从用 C# 编写的 .Net COM 可见 DLL 调用方法。我有那个工作。现在我需要让它处理来自同一 DLL 的传入进度通知事件。我昨天问了一个类似的问题,其中 VB6 IDE 甚至没有看到 DLL 有事件提供。该问题已通过正确装饰 C# 接口(interface)和类得到解决。

首先是C#代码z:

namespace NewTricksDLL
{
    [ComVisible(true)]
    [Guid("16fb3de9-3ffd-4efa-ab9b-0f4117259c75")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface ITransfer
    {
        [DispId(2)]
        string SendAnEvent();
    }

    [ComVisible(true)]
    [Guid("16fb3de9-3ffd-4efa-ab9b-0f4117259c74")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IManagedEventsToCOM
    {
        [DispId(2)]
        void NotificationEvent();

    }

    [ComVisible(true)]
    [Guid("dcf177ab-24a7-4145-b7cf-fa06e892ef21")]
    [ComSourceInterfaces(typeof(IManagedEventsToCOM))]
    [ProgId("ADUTransferCS.NewTricks")]
    public class NewTricks : ITransfer
    {
        public delegate void NotificationEventHandler();
        public event NotificationEventHandler NotifificationEvent;

        public string SendAnEvent()
        {
            if (NotifificationEvent != null)
                NotifificationEvent();           
        }
    }
}

现在我尝试在 VB6 中使用它。请注意,_tricky_NotificationEvent 事件处理程序是由 IDE 通过从左侧下拉列表中选择 _tricky 并从右侧下拉列表中选择 NotificationEvent 生成的,因此我知道此事件对 VB6 IDE 可见。

Option Explicit

Public WithEvents _tricky As NewTricksDLL.NewTricks

Private Sub Command1_Click()
    ' The next line fails with 'Object or class does not support the set of events'
    Set _tricky = CreateObject("NewTricksDLL.NewTricks")
    ' Execution never makes to the next line
    _tricky.SendAnEvent()

End Sub

Private Sub _tricky_NotificationEvent()
    ' This handler was auto generated by the IDE
End Sub

最佳答案

希望这可以有所帮助 - 这是您的要求的最小裸骨 VB.net 实现:VB6 可使用的 COM 接口(interface),一个事件,一种方法。

Option Explicit On
Option Strict On

<ComClass(newTricks.ClassId, newTricks.InterfaceId, newTricks.EventsId)>
Public Class newTricks

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "386d540d-f8b8-46e1-939d-7b69dd5eff0a"
    Public Const InterfaceId As String = "78b4036e-86a0-4671-997d-da5a33bf026f"
    Public Const EventsId As String = "7b0fa5b5-b45e-4db2-9282-c06e09852161"
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()
    End Sub

    Public Event NotificationEvent()

    Public Sub SendAnEvent()
        RaiseEvent NotificationEvent()
    End Sub
End Class

这是通过启动一个新项目(Windows 类库)创建的,从项目中删除自动创建的 Class1.vb,添加一个 COM 类项并将其重命名为 NewTricks。然后添加事件声明和子声明和代码;还添加了 Option 语句。构建项目。

此 VB6 代码已成功使用。单击该按钮会导致“事件已触发”被写入即时窗口。使用 NewCreateObject 方法创建对 newTricks 的引用是成功的。

Option Explicit

Private WithEvents oTricks As NewTricksDll.newTricks

Private Sub Command1_Click()

  Set oTricks = New NewTricksDll.newTricks
  'Set oTricks = CreateObject("NewTricksDll.newTricks")

  oTricks.SendAnEvent

End Sub

Private Sub oTricks_NotificationEvent()
  Debug.Print "Event fired"
End Sub

这里是 VB.net 代码对应的 C# 代码,由 https://converter.telerik.com/ 直接转换

using Microsoft.VisualBasic;

[ComClass(newTricks.ClassId, newTricks.InterfaceId, newTricks.EventsId)]
public class newTricks
{

    // These  GUIDs provide the COM identity for this class 
    // and its COM interfaces. If you change them, existing 
    // clients will no longer be able to access the class.
    public const string ClassId = "386d540d-f8b8-46e1-939d-7b69dd5eff0a";
    public const string InterfaceId = "78b4036e-86a0-4671-997d-da5a33bf026f";
    public const string EventsId = "7b0fa5b5-b45e-4db2-9282-c06e09852161";

    // A creatable COM class must have a Public Sub New() 
    // with no parameters, otherwise, the class will not be 
    // registered in the COM registry and cannot be created 
    // via CreateObject.
    public newTricks() : base()
    {
    }

    public event NotificationEventEventHandler NotificationEvent;

    public delegate void NotificationEventEventHandler();

    public void SendAnEvent()
    {
        NotificationEvent?.Invoke();
    }
}

我还没有尝试过这个 C# 代码。

关于com - C# 到 VB6 COM 事件 (“object or class does not support the set of events” ),但不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59720868/

相关文章:

python - 在 python 中调用 vb dll

windows - 从 64 位应用程序使用 32 位进程内 COM 服务器的简单方法有哪些?

delphi - 如何在 COM 服务器中引发异常?

c++ - 调用 HideUI 后,mshtml 失败并显示 FAST_FAIL_INCORRECT_STACK

vba - 通过循环反复检查整个脚本字典是不好的做法吗? VB6

.net - .NET Framework 安装是否会干扰现有的 VB6 运行时或 COM 安装?

c# - 将简单的 C# DLL 转换为 COM 互操作组件

c#-4.0 - COM Interop 中动态代码的内存泄漏

c++ - Windows shell 扩展教程不会将 CLSID 添加到注册表

c++ - IDispatch::Invoke(DISPATCH_PROPERTYGET) 是否会增加返回的 IDispatch 接口(interface)的引用计数?