Working on creating a .NET 8 library which will be called from Excel VBA via COM interop. I've had some success setting this up using regsvr32, but having gone down that path on earlier projects, I'm very attracted to the idea of "reg-free COM". It would make things a lot easier for me. Of course, it's giving me a bit of trouble.
First off, I've been following these two pieces of guidance:
Expose .NET Core components to COM
How to correctly create COM classes with .NET8?
Per that guidance, I've used the DSCOM tool to generate my .tlb file, which Excel can reference.
This is my project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableComHosting>true</EnableComHosting>
<EnableRegFreeCom>true</EnableRegFreeCom>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Runtime.InteropServices" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="dSPACE.Runtime.InteropServices.BuildTasks" Version="1.15.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<DsComTypeLibraryEmbedAfterBuild>true</DsComTypeLibraryEmbedAfterBuild>
<DsComOverideLibraryName>MyTest</DsComOverideLibraryName>
</PropertyGroup>
</Project>
As you can see, I have EnableRegFreeCom set. I am getting all the following files from my build:
MyTest.COM.dll
MyTest.COM.tlb
MyTest.COM.comhost.dll
MyTest.COM.X.manifest
[plus a few others I don't thing are relevant]
I have the following simple test object I'm attempting to use:
[assembly: ComVisible(true)]
[assembly: ClassInterface(ClassInterfaceType.None)]
namespace MyTest.COM
{
[Guid("c99bc767-9def-4f24-8e6c-dc89496f90d8")]
public class COMDebug : ICOMDebug
{
public int Add(int x, int y) => x + y;
}
[Guid("ac1bd331-2979-4ad3-ae29-d839d2d9d64c")]
public interface ICOMDebug
{
int Add(int x, int y);
}
}
I've found a few places that give examples of how to use regfree COM from VBA. This answer specifically says it is possible and gives a psudo-example. Here is my non-working VBA code, running from Excel:
Sub Test()
Dim ctx
Dim dbg
Dim r As Integer
Set ctx = CreateObject("Microsoft.Windows.ActCtx")
ctx.Manifest = "C:\Path\To\Files\MyTest.COM.X.manifest"
Set dbg = ctx.CreateObject("MyTest.COM.COMDebug")
r = dbg.Add(2, 2)
MsgBox b
End Sub
The expression ctx.CreateObject("MyTest.COM.COMDebug") throws an error:
Run-time error '-2147221231 (80040111)':
Automation error
ClassFactory cannot supply requested class
My research has not been able to turn up much helpful info on this problem. I've verified that the ProgId I'm using matches what's output into the manifest file. All my output files are in the same folder- I've even tried putting all of them into the same folder as Excel.exe just as a test. The above error message is also different than what I get if I try to use CreateObject on a ProgId that doesn't exist, or if I try to use CreateObject("MyTest.COM.COMDebug") without a customized ActCtx object, so I feel like I am on the right track.
Any idea how to make this work? Or why it isn't working?
EDIT:
This question was also pointed out to me: Exact steps for registration-free COM interop in .NET (invoke copied COM dll without regsvr32) It's one I hadn't seen, but it involves consuming regfree COM from a custom application being authored (like another .NET app). I don't see a way to apply this information to my problem in consuming the COM dll from Excel VBA.