3
votes

My client has a VB6 program installed on a large number of computers around the world. It now needs to access an external system via a REST API. I created a Class Library in VB.Net targeting .NET Framework 4. (That's the most recent version installed everywhere.) The DLL exposes about a dozen public functions and subroutines, and ~40 properties. I tested the DLL using this PowerShell code:

[System.Reflection.Assembly]::LoadFile( "$directorypath\Debug\MyExample.dll")
$quotaInstance = new-object MyExample.ComClass1

All of the methods and properties are accessible from the PS script. When I load the DLL into the VB6 IDE, however, the object browser only shows the methods, not the properties. If I can't figure this out, I will have to re-code them as a bunch of functions and subroutines. I hate that idea.

The question How to make properties visible to COM in a .NET DLL (Methods DO work) looks similar, but I'm not (explicitly, see below) using an interface, and I'm not certain that the question was even ever answered.

Does anyone know what's going on, and (more importantly) how to fix it? Thanks!

Update: People have asked to see my code, so here is a striped down sample. I'm guessing from the InterfaceId that Visual Studio Community 2017 is creating an interface of some sort for me.

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

#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 = "099bfc91-1f82-4a26-b1e0-d9645bb1714d"
    Public Const InterfaceId As String = "13e9763d-455c-4d89-8323-cc4e7ae7648e"
    Public Const EventsId As String = "773feeba-e635-4411-b175-30b345afa841"
#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

    ' *** Auto-implemented properties
    ' When you declare an auto-implemented property, Visual Basic automatically
    ' creates a hidden Private field called the backing field to contain the
    ' Property value. The backing field name is the auto-implemented Property
    ' name preceded by an underscore (_).

    Public Property Foo As String
    Public Property Bar As Integer

    Public Function InitiateSession(ExampleServer As String) As Boolean
        ' Creates a new API_session.
        ' Returns True if the connection was successful, otherwise False
        ' ...
    End Function

    Public Sub CloseSession()
        ' Releases the current API_session.
        ' ...
    End Sub
End Class
3
"how to fix it?" - Fix what? You have not shown us how the class is specified. That said, they made this extremely easy for VB. see: ComClassAttribute. That will tell the compiler to generate the needed interfaces and to properly decorate them with the need attributes.TnTinMn
@TnTinMn I had already done all of that, and as I said, Powershell could see the properties, but not an older version of VB.samwyse
For some reason, the interface generation implemented by the compiler for ComClass does not work for auto-implemented properties. You will need to use long form with the Get and Set. Also stating that a .Net application like Powershell can see a .Net net class in pointless.TnTinMn
@TnTinMn Thanks! Make that an answer and I'll mark it as the accepted answer.samwyse

3 Answers

3
votes

For some unknown reason, the automatic interface generation provided by the VB Compiler for classes marked with the ComClassAttribute ignores auto-implemented properties. You need to explicitly code the long-form for properties.

So instead of the auto-implemented form of:

Public Property Foo As String

You need:

Private _Foo As String
Public Property Foo As String
    Get
        Return _Foo
    End Get
    Set(value As String)
        _Foo = value
    End Set
End Property

for Foo to be included in the COM interface.

0
votes

I am not much of VB fan, but hope below example helps

Public Class Class1
    Implements IClass1

    Property Property_1 As Int32 Implements IClass1.Property_1
        Get
            Return Property_1
        End Get
        Set(value As Int32)
            Property_1 = value
        End Set
    End Property
End Class

Public Interface IClass1
    Property Property_1 As Int32
End Interface
0
votes

If your properties are of a generic type like List<T> they cannot be exported to COM.

If this is the case you should see some build warnings from the .NET compiler indicating such.

(The question doesn't show an example so I don't know if this is the case here.)