我可以将 .NET 5 COM 互操作对象与 VB6 连接起来吗?

Posted

技术标签:

【中文标题】我可以将 .NET 5 COM 互操作对象与 VB6 连接起来吗?【英文标题】:Can I connect a .NET 5 COM interop object with VB6? 【发布时间】:2021-11-27 15:25:13 【问题描述】:

我一直在研究 .NET Core COM 互操作和how to expose them。

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

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

如果这个问题不属于这里,我很抱歉,但是有人可以解释一下这个问题吗?

【问题讨论】:

只要付出足够的努力,一切皆有可能。你为什么想要? VB6 是一种死语言。不只是大部分都死了,它是检查口袋里的零钱死了。 无论如何,你需要更具体一些。你尝试过什么,结果如何?包括您收到的任何错误消息。 等等,你想从 VB6 调用一些 .NET 代码吗?甚至不是.NET的VB6?是的,不要那样做。我想这是可能的,但有些事情你真的不应该做。 VB6 是在 20 多年前推出的,从那时起事情就发生了变化。甚至 VB.NET 自 2002 年以来就已经存在,我认为它不会与 .NET 核心兼容 @Neil 我真的不想这样做,但我工作的公司的主要产品完全是用 VB6 编码的,他们需要我这样做......所以我就是想知道这个。他们过去已经使用了一些来自 VB6 的 .NET Framework 项目。但如果它仍然看起来超级不可能,那么我就会忘记它。谢谢你的回答! VB6 只对那些不需要支持它为生的人来说是死的(而且不一定要选择“更好”的东西)。长期以来,对于许多开发人员 (IMO) 而言,逐渐将部分 VB6 应用程序迁移到 .NET - 或在那里制作新组件 - 非常普遍。 【参考方案1】:

.NET Framework、.NET Core 3+ 和 .NET 5+ 可以将 COM 对象公开给 COMworld。这个世界包括 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 并确保您编译 for 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

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) 运行

注意 1: 你也可以使用 ProgId 属性,就像 COM 对象经常做的那样,你不必只使用 Guids...

注意 2: 我只使用了IDispatch(“延迟加载”)接口进行此演示,但您也可以使用IUnknown 派生接口(“早期加载”)和 TLB .不幸的是,.NET 5 不会为您创建 .TLB,您必须自己构建它或使用其他工具创建它,然后将其导入 .NET 和/或 VB6。

【讨论】:

谢谢你一百万次的解释和西蒙的例子! 那么,不再像 .NET 框架中那样使用 regtlb 了吗? @StayOnTarget - 这是 regasm,而不是 regtlb,但是是的,它们改变/破坏了 COM 中从 .NET Framework 到 .NET Core 的许多东西...... .NET Core 没有构建任何嵌入.dll 或外部 .tlb 了。 @Biel - 我的 VB6 有点生锈,但我认为你必须使用早期加载才能使用 WithEvents,即:有一个 tlb。,即:你仍然可以使用 CreateObject 但你不能像我的示例那样使用无类型的 VB6 对象。 @Biel 但如果你绝对必须,请参阅docs.microsoft.com/en-us/archive/msdn-magazine/2001/march/…。

以上是关于我可以将 .NET 5 COM 互操作对象与 VB6 连接起来吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中使用 COM 互操作对象

COM Interop .NET 程序集 - 一个术语问题

如何通过 COM 互操作在 .NET 对象上调用静态方法?

在 VB.NET 中使用 Word 和 Outlook 2007 的 Office 互操作

如何将聚合 .NET COM 互操作添加到 ATL EXE 服务器?

Vista 中的 VB6 .NET 互操作问题