Question

I've got a particularly tricky situation here that I would like to throw out there for a bit more feedback on (I'm the only .NET dev in the company I work for so no-one to bounce off).

I've been tasked with replacing an aging VB6 authored ActiveX component that is consumed by an application that contains both VB6 useage and VB.NET usage of the component I'm replacing.

I have the complete source code for all these components so I can see the use cases.

For the sake of this discussion the components could be called:

MyVb6.dll
MyApp (with VB.NET & VB6 Components)

During the build process for MyApp they make use of TlbImp tool to then produce an interop library:

Interop.MyVb6.dll

Usage

In most instances the usage of this is as expected, making use of the CreateObject() method such as:

Private Property MyProp() As Object
    Get
        Try
            If m_myProp Is Nothing Then
                m_myProp = CreateObject("MyVb6.MyVb6Obj")
                m_myProp.Initialize()
            End If
        Catch : End Try
        Return m_myProp
    End Get

However in one instance I've found they appear to have changed tactic on how to consume this interop dll and they have a static reference to it and a typed property, such as:

Private Property MyProp() As MyVb6.MyVb6ObjClass 'Whilst this is strongly typed, it is from the interop dll ...
    Get
        If m_myProp Is Nothing Then
            m_myProp = CreateObject("MyVb6.MyVb6Obj")
            m_myProp .Initialize()
        End If
        Return m_myProp 
    End Get

The expense of rebuilding and redeploying the entire application is completely out of the question so I'm left with no option other than to replace just the MyVb6.dll.

What I'm hoping to find out here is if this is a practical solution ...

Replacement

What I have done so far is written the skeleton of the replacement dll and since the object instances are created using a known string value I have added this is the ProgId, such as:

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("xxx")]
[ProgId("MyVb6.MyVb6Obj")]
public class MyNewCSharpVersion : IMyNewCSharpVersion
{
    ...
}

Obviously for each of the objects I have maintained an identical interface so the calling application will find all the expected methods to call etc.

Then when I deploy this I'll deregister the old COM component and register my new one. Will this attempt at tricking it into thinking it's creating the same object actually work?

The Very Nasty Problem

There are also examples in the source code where they have used the VB6 dll directly, such as:

Dim myObj As MyVb6.MyVb6Obj

Unfortunately, no-one can answer the question if this particular component is still in use which in itself is slightly worrying.

If anyone has done something similar and got it working it would be great to know.

Was it helpful?

Solution

Not a problem, just use the right names:

namespace MyVb6 {
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("xxx")]
    public class MyVb6Obj : _IOldVb6Version
    {
        ...
    }
}

Note the different interface name. Don't write your own. Add a reference to the old VB6 component so you can be completely sure that you implement the IOldVb6Version interface accurately with an exact match on the IID, the methods, their order and their arguments. If you don't know the old interface name then have a look with Oleview.exe, File + View Typelib.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top