4

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.

MarkJ
  • 30,070
  • 5
  • 68
  • 111
Jammer
  • 9,969
  • 11
  • 68
  • 115
  • AFAIK it is not possible to do this: .net dll -> com -> .net dll. However, you could possibly do this: .net dll -> com -> vb6 dll -> com -> .net dll – Aaron Carlson Feb 17 '14 at 19:06
  • You should consider picking up a copy of Adam Nathan's book [.NET and COM: The Complete Interoperability Guide](http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X). It has a chapter specifically on how to reimplement a COM interface in a .NET component, as well as lots of other good info. – Holistic Developer Feb 18 '14 at 04:22

1 Answers1

6

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    Ahhhh, OK. The old VB6 component doesn't have any interfaces defined but I think this should work if I use the interfaces generated in the TblImp generated Interop dll ... seems hideous but if that's what it takes ... – Jammer Feb 17 '14 at 20:22
  • 2
    It does have interfaces, they are just hidden. But certainly very visible if you use Oleview or Tlbimp. It is not hideous, isolating the implementation from the interface is a standard interop approach that very common in .NET as well. Please close your question. – Hans Passant Feb 17 '14 at 20:31
  • I use interfaces a lot in general coding it just feels a bit messy keeping old stuff laying around I guess. Thanks for the info Hans, much appreciated. – Jammer Feb 17 '14 at 20:34