3
votes

I am aware of a 10 year old question with the same title as this one but I have double checked and I am not mistakenly using the delegate name. This is a different issue.

Here at work we have an old VB6 application I need to teach new(er) tricks. The first thing I had to do was have it call methods from a .Net COM-visible DLL written in C#. I have that working. Now I need to have it handle incoming progress notification events from that same DLL. I asked a similar question yesterday wherein the VB6 IDE was not even seeing that the DLL had events to offer. That issue was solved by decorating the C# interfaces and classes correctly.

First, the C# codez:

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();           
        }
    }
}

An now my attempt to use it in VB6. Please note that the _tricky_NotificationEvent event handler was generated by the IDE by picking _tricky from the left-hand dropdown and NotificationEvent from the right-hand dropdown so I know this event is visible to the 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
2
Does this answer your question? Exposing .NET events to COM?GSerg
@GSerg No, because it looks like what I already have. It does include exposing async tasks via the interface, which I need to do next, so thanks for that. :)davecove
You are missing the [ClassInterface(ClassInterfaceType.None)] though, but I'm not sure if it matters.GSerg
It didn't seem to. I had tried it before (and just did again) and it didn't help.davecove
What's the exact line which gives you the error?StayOnTarget

2 Answers

1
votes

Hopefully this can help - here's a minimal bare bones VB.net implementation of your requirements: COM interface consumable by VB6, one event, one method.

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

This was created by starting a new project (Windows class library), delete from the project the Class1.vb that's automatically created, add a COM Class item renaming it to NewTricks. Then added the event declaration and the sub declaration and code; also added the Option statements. Built the project.

This was successfully used from this VB6 code. Clicking the button resulted in "Event fired" being written to the immediate window. This was successful with using both New and CreateObject methods of creating the reference to 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

Here is the corresponding C# code for the VB.net code, as converted straight-up by 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();
    }
}

I have not tried this C# code.

0
votes

If you use CreateObject, it creates an object of type Object I believe. You should create the object simply by using New:

Set _tricky = New NewTricksDLL.NewTricks

Since you declared the variable as WithEvents, you can't just declare it using As New NewTricksDLL.NewTricks which I imagine you probably tried.