我能否将.NET 5 COM互操作对象与VB6连接?

5

我一直在研究.NET Core COM互操作和如何公开它们

虽然我在得出结论和理解某些概念方面遇到了一些问题。 我的老板告诉我,他们做了一些测试,并认为创建可从VB6内部调用的C#代码(包括事件)的唯一方法是创建.NET Framework项目,因为在.NET Core 3.1中不可用(当时他们必须使用此功能)。

但是看到之前提到的页面并进行更多的研究,我确实认为.NET Core支持这种互操作性。而且我不明白为什么.NET Core平台不能做到这一点。

如果这个问题不属于这里,请原谅,但能否有人解决这个问题?


2
只要付出足够的努力,任何事情都是可能的。但你为什么想要这样做呢?VB6已经是一门死亡的语言了,不仅仅是大部分死亡,而是连口袋里的零钱都找不到的死亡。 - Robert Harvey
@Neil,我真的不想这么做,但我工作的公司主要产品完全是使用VB6编写的,他们需要我这么做……所以我才会有这个疑问。他们之前已经在VB6中使用了一些.NET Framework项目。但如果看起来仍然非常不可能,那我就忘了它吧。感谢你的回答! - Biel
@RobertHarvey 我们的主要产品完全使用VB6编写,我们的老板想创建一些“桥梁”项目,以开始在.NET中进行编码...尽管现在仍然在VB6中使用该.NET代码。如果我没有恰当地解释自己,请原谅我,谢谢。 - Biel
@RobertHarvey 我还没有尝试过任何东西,至少在.NET Core方面是这样的。我知道它对于.NET Framework肯定有效,因为我们已经创建了一些类似的项目,但只是想知道它是否支持新版本的.NET Core。 - Biel
5
VB6 只对那些不需要靠它来赚钱(并且不一定能选择更好的东西)的人而言才是死亡的。在很长一段时间内,对于许多开发人员(依我之见),将 VB6 应用程序的部分逐渐迁移到 .NET 或在该平台上创建新组件已经相当普遍了。 - StayOnTarget
显示剩余3条评论
1个回答

10

.NET Framework、.NET Core 3 和 .NET 5/6/+ 可以将 COM 对象暴露给 COM 世界。这个世界包括 VB6 和所有可以使用 COM 的东西。

a)创建一个 .NET 5“NetClassLibrary”类库项目(例如使用 Visual Studio)

b)添加一个名为 NetComObject.cs 的文件,例如以下代码:

using System;
using System.Runtime.InteropServices;

namespace NetClassLibrary
{
    [ComVisible(true)]
    [Guid("cfb2ee8b-f2ec-447c-9f0d-ac19c9a6cc26")] // TODO: change this GUID
    public class NetComObject
    {
        public string SayHello() => "Hello World from .NET " + RuntimeInformation.FrameworkDescription;
    }
}

c) 修改.csproj文件,将EnableComHosting属性设置为true,并确保编译时选择x86,因为VB6是32位程序(注意,如果您使用Excel的64位VBA而不是VB6,则必须选择64位编译),例如:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <EnableComHosting>true</EnableComHosting>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>

</Project>

d) 编译后,启动管理员权限的命令提示符,并运行此命令:

regsvr32 yourPathTo\NetClassLibrary.comhost.dll

enter image description here

e) 创建一个VB6项目,添加以下VB6代码:

Private Sub Form_Load()

    Dim obj As Object
    Set obj = CreateObject("new:{cfb2ee8b-f2ec-447c-9f0d-ac19c9a6cc26}") // TODO: use the same GUID!

    MsgBox obj.SayHello()

End Sub

f) 运行

enter image description here

注意1:你也可以使用ProgId属性,就像COM对象经常这样做一样,你不必仅限于使用Guid...

注意2:我只在示例中使用了IDispatch("延迟加载")接口,但你也可以使用从IUnknown派生的接口("早期加载")和TLBs。不幸的是,.NET 5不会为你创建.TLB,你必须自己构建它或使用另一个工具创建它,并将其导入到.NET和/或VB6中。


1
非常感谢你的解释和示例,Simon! - Biel
@StayOnTarget - 不确定你的意思是什么,regtlb是什么? - Simon Mourier
2
@StayOnTarget - 这是regasm,而不是regtlb,但是没错,从.NET Framework到.NET Core的COM移植中他们改变/破坏了许多东西... .NET Core不再构建任何嵌入在.dll或外部.tlb中的内容。 - Simon Mourier
2
@Biel - 我的VB6有点生疏,但我认为你必须使用早期加载才能使用WithEvents,即:需要一个tlb文件。也就是说,你仍然可以使用CreateObject,但不能像我的示例中那样使用未经过类型定义的VB6对象。 - Simon Mourier
1
@Biel但如果你非常必须,可以参考https://learn.microsoft.com/en-us/archive/msdn-magazine/2001/march/com-handle-late-bound-events-within-visual-basic-using-an-atl-bridge。 - GSerg
显示剩余4条评论

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