使用C#重新构建VB6 COM类的更新

4

我有一个特别棘手的情况,需要向大家请教一下(因为我是公司里唯一的.NET开发人员,没有人可以交流)。任务让我替换一个老旧的VB6编写的ActiveX组件,这个组件被应用程序消耗,包含了使用VB6和VB.NET的组件。

我拥有所有这些组件的完整源代码,所以可以看到使用情况。

为了讨论方便,这些组件可以称为:

MyVb6.dll
MyApp(带有VB.NET和VB6组件)

MyApp的构建过程中,它们使用TlbImp工具来生成一个互操作库:

Interop.MyVb6.dll

用法

在大多数情况下,使用方法如预期,使用CreateObject()方法,例如:

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

然而在某些情况下,我发现他们更改了消耗此互操作dll的策略,他们使用了静态引用和类型化属性:

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

重新构建和重新部署整个应用程序的费用完全不可行,所以我别无选择,只能替换MyVb6.dll

我希望在这里找到的是这是否是一个实际可行的解决方案...

替换

到目前为止,我已经编写了替换dll的框架,并且由于对象实例是使用已知的字符串值创建的,所以我将其添加为ProgId,例如:

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

显然,我已经为每个对象维护了相同的接口,这样调用应用程序将找到所有预期的方法等。

然后,当我部署它时,我将注销旧的COM组件并注册我的新组件。 这种尝试欺骗它以认为正在创建相同的对象是否实际有效?

非常棘手的问题

源代码中还有一些直接使用VB6 dll的示例,例如:

Dim myObj As MyVb6.MyVb6Obj

不幸的是,没有人能回答这个问题,是否仍在使用这个特定的组件,这本身就有点令人担忧。

如果有人做过类似的事情并且使其工作正常,那就太好了,让我们知道一下。


据我所知,不可能做到这一点:.net dll -> com -> .net dll。然而,你可能可以这样做:.net dll -> com -> vb6 dll -> com -> .net dll。 - Aaron Carlson
你应该考虑购买亚当·内森的书《.NET和COM:完全互操作性指南》(http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X)。它有一章专门介绍如何在.NET组件中重新实现COM接口,还有很多其他有用的信息。 - Holistic Developer
1个回答

6
没问题,只需要使用正确的名称即可:
namespace MyVb6 {
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("xxx")]
    public class MyVb6Obj : _IOldVb6Version
    {
        ...
    }
}

请注意不同的接口名称。不要自己编写。添加对旧版VB6组件的引用,以便您可以完全确信准确地实现IOldVb6Version接口,包括IID、方法、顺序和参数完全匹配。如果您不知道旧接口名称,请使用Oleview.exe查看Typelib。


1
啊,好的。老的VB6组件没有定义任何接口,但如果我使用TblImp生成的Interop dll中生成的接口,我认为这应该可以工作……看起来很丑陋,但如果这是必要的话…… - Jammer
2
它确实有接口,只是被隐藏了。但是如果您使用Oleview或Tlbimp,它们肯定非常可见。这并不难看,将实现与接口隔离是.NET中非常常见的标准互操作方法。请关闭您的问题。 - Hans Passant
我在一般编码中经常使用接口,只是感觉保留旧的东西有点凌乱。谢谢信息,汉斯,非常感谢。 - Jammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接