5

I have been doing some research on .NET Core COM interop and how to expose them.

Though I am having some issues coming up with a conclusion and understanding some concepts. My boss told me they did some tests and they thought the only way to create C# code that could be called from within VB6 (including events) was to create a .NET Framework project, as it was not available in .NET Core 3.1 (at the moment they had to use this feature).

But seeing the previously mentioned page and doing some more research, I do think it looks like .NET Core supports this interoperability. And I do not understand why wouldn't it be possible for the .NET Core platform to do this.

I am sorry if this question does not belong here, but could someone shed some light on this issue?

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
Biel
  • 193
  • 1
  • 3
  • 15
  • 2
    Anything is possible given enough effort. Why would you want to? VB6 is a dead language. Not just mostly-dead, it is check the pockets for loose change dead. – Robert Harvey Oct 07 '21 at 14:19
  • In any case, you need to be more specific. What have you tried, and what was the result? Include any error messages you are getting. – Robert Harvey Oct 07 '21 at 14:21
  • Wait, you want to call some .NET code from VB6? VB6 that isn't even .NET? Yeah, don't do that. I guess it's possible, but there are some things you really shouldn't do. VB6 was launched over 20 years ago, and things have moved on since then. Even VB.NET has been around since 2002 and I wouldn't think that would be compatible with .NET core – Neil Oct 07 '21 at 14:27
  • @Neil I really do not want to do it, but the main product of the company I work for is totally coded in VB6 and they need me to do it... so that is why I was wondering this. They already used some .NET Framework projects from VB6 in the past. But if it still seems super impossible then I'll just forget about it. Thank you for answering! – Biel Oct 07 '21 at 14:35
  • @RobertHarvey Our main product is totally coded in VB6, and our boss wants to create some "bridge" projects to start coding it in .NET... though still using that .NET code in VB6 for now. I am sorry if I am not explaining myself properly and thank you. – Biel Oct 07 '21 at 14:36
  • @RobertHarvey And I haven't tried anything at all yet, at least with .NET Core. I know for sure it works for .NET Framework, because we already created some projects like this, but just wanted to know if it was supported for the new versions of .NET Core. – Biel Oct 07 '21 at 14:37
  • The documentation seems to suggest that it is supported. Why do you need .NET Core? VB6 won't run on Linux, AFAIK. – Robert Harvey Oct 07 '21 at 14:38
  • 5
    VB6 is only dead to people who don't have to support it for a living (and don't necessarily get to choose something "better"). For a long time, for many devs (IMO) gradually migrating parts of VB6 apps to .NET - or making new components there - has been quite common. – StayOnTarget Oct 08 '21 at 11:24

1 Answers1

8

.NET Framework, .NET Core 3, and .NET 5/6/+ can expose a COM object to the COM world. This world includes VB6 and everything that can do COM.

a) Create a .NET 5 "NetClassLibrary" Class Library project (using Visual Studio for example)

b) Add a NetComObject.cs file with the following code for example:

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) Modify the .csproj to set the EnableComHosting property to true and make sure you compile for x86 as VB6 is a 32-bit program (note if you use Excel's 64-bit VBA, not VB6, you must compile for 64-bit), like this for example:

<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) Compile, start an admin prompt and run this:

regsvr32 yourPathTo\NetClassLibrary.comhost.dll

enter image description here

e) Create a VB6 project, add this VB6 code:

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) Run

enter image description here

Note 1: you can use a ProgId attribute too, like COM object often do, you don't have to stick to Guids only...

Note 2: I've only used IDispatch ("Lazy Loading") interface for this demonstration but you can use IUnknown-derived interfaces ("Early Loading") and TLBs too. Unfortunately .NET 5 doesn't create the .TLB for you, you'll have to build it by yourself or create it with another tool and import it in .NET and/or in VB6.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • 1
    Thank you a million times for the explanation and the example Simon! – Biel Oct 08 '21 at 06:39
  • So, no more regtlb like in .NET framework? – StayOnTarget Oct 08 '21 at 11:26
  • @StayOnTarget - Not sure what you mean by that, what is regtlb? – Simon Mourier Oct 08 '21 at 12:06
  • @SimonMourier sorry I should have expanded... in .NET 4x I think the procedure was to compile your COM-exporting C# code to a DLL + a separate TLB file, and then you would register the TLB with regtlb. You couldn't use regscr32 at all on the DLL itself. It seems like they've changed that procedure now. – StayOnTarget Oct 08 '21 at 14:39
  • 2
    @StayOnTarget - It's regasm, not regtlb, but yes, they change/broke many things in COM moving from .NET Framework to .NET Core... .NET Core doesn't build any embedded in .dll or external .tlb anymore. – Simon Mourier Oct 08 '21 at 15:05
  • @SimonMourier thanks! – StayOnTarget Oct 08 '21 at 16:04
  • @SimonMourier Hey Simon, sorry for disturbing again but, do you know how should events be handled from VB6 if using .NET Core? I have found [this post](https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-3.0/dd8bf0x3(v=vs.85)?redirectedfrom=MSDN) but since we are using `CreateObject` here, I don't know how to register the evens in VB6. Sorry and thanks again! – Biel Oct 20 '21 at 14:30
  • 2
    @Biel - My VB6 is a little bit rusty but I think you must use early loading to be able to use WithEvents, ie: have a tlb around., ie: you can still use CreateObject but you cannot use an untyped VB6 object like in my example. – Simon Mourier Oct 20 '21 at 15:17
  • 1
    @Biel But if you absolutely must, see https://learn.microsoft.com/en-us/archive/msdn-magazine/2001/march/com-handle-late-bound-events-within-visual-basic-using-an-atl-bridge. – GSerg Oct 28 '21 at 07:35