Previous | Index | Next 

[HOWTO] Fix VB6 client applications that reference a COM DLL that has migrated to VB.NET using binary compatibility

The BinaryCompatibility pragma allows you to generate a .NET DLL that is binary-compatible with an existing VB6 (COM) DLL, so that all existing compiled COM clients continue to work as before.

However, this pragma can’t ensure that the client VB6 application can be run as-is from inside the VB6 IDE and/or re-compiled against the .NET DLL. In fact, it is highly probable that you’ll need to edit the VB6 code to account for minor differences. These differences are caused by COM Interop and aren’t to be considered as limitations of VB Migration Partner and its BinaryCompatibility pragma.

Here’s a list of the changes you might need to make to the original VB6 project to compile it against a .NET DLL that is binary-compatible with a VB6 DLL that was originally referenced by the VB6 project.

1) Compound namespace names require fixing
Most .NET DLL have a compound name, formed by joining the company name and the library name, as in “CodeArchitects.Helpers”. When you export this library to COM, the dot in the name is replaced by the underscore character, therefore a VB6 client application must reference the library using the following syntax:

        Dim wi As CodeArchitects_Helpers.Widget 

2) Enum values must be prefixed by the enum class name.
A well-known limitation of COM Interop is that enum constants are automatically prefixed by the name of the enum type followed by an underscore. For example, let’s assume that the VB6 client references a COM DLL that exposes an Enum named Gender, defined as follows

        Public Enum Gender
            Male
            Female
        End Enum

Next, assume that the VB6 client uses the enum as in this code:

        Dim gen As Gender
        gen = Male

If you now migrate the COM DLL into a binary-compatible .NET DLL, the compiled VB6 client continues to work as before. However, if you later need to recompile the VB6 client you need to modify this code as follows:

        Dim gen As Gender
        gen = Gender_Male

3) Auto-instancing variables may require a “Class” suffix
Let’s assume that a COM DLL exposes a class named Widget and that a VB6 client application contains this code:

        Dim wi As New Widget

If you now migrate the DLL, the resulting VB.NET project contains two related types: the WidgetClass creatable class and the Widget interface. In most cases, the existing VB6 code works correctly even if now the Widget symbol refers to an interface rather than a creatable class.

In a few cases, however, it is necessary that you explicitly reference the class rather then the interface, by appending the “Class” suffix:

        Dim wi As New WidgetClass

Failing to do so results in a VB6 compilation error “Invalid use of New keyword”.

4) Auto-instancing variables may require splitting in two statements
This is a variant of previous case and occurs if the class being instantiated is a collection class. For example, let’s assume that WidgetCollection is a collection class that contains Widget objects and that can be enumerated by means of a For Each loop:

        Dim widgets As New WidgetCollection
        '...add elements here
        For Each  wi In widgets
            '...
        Next

You already know that you have to edit the first Dim statement and append the “Class” suffix. However, if WidgetCollection is a collection class this edit doesn’t suffice, because you’ll get a runtime error 438 (“Object doesn’t support this property or method”) when the For Each statement is executed.

The only way to work around this error is by splitting the declaration into two distinct statements:

        Dim widgets As WidgetCollection          ' interface variable
        Set widgets = New WidgetCollectinClass   ' creatable class
        '...add elements here
        For Each wi In widgets                   ' now this works
            '...
        Next

 

Previous | Index | Next