I am trying to call .NET Core 8 (C#) code from C++ dll in Excel VBA.
The architecture I’m targeting is:
Excel (VBA) → C++ native DLL → .NET Core 8 C# DLL
The idea is that the VBA code calls the native DLL, and that DLL hosts the .NET Core runtime and forwards the call to a [UnmanagedCallersOnly] static method inside my C# assembly.
In my real project, VBA is not the final target — I only use Excel/VBA here as a simple test harness for my proof of concept. However, in the final architecture, other constraints force me to go through a native C++ DLL as the entry point, which then has to call into the C# .NET Core code.
My POC Project : (many paths are hard coded case is only a POC) https://drive.google.com/file/d/1hE2NVuktjwj2rp-7oRcvEcpqiMYAw9b0/view?usp=sharing
If you have a simple POC project for load C# Core (8.0 if posible) with an C++ (20 if posible) dll in 64 t'is perfect ;)
Details :
C# code (cs_core.dll) :
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace MyNamespace;
public static class ManagedExports
{
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })]
public static int Add(int a, int b) => a + b;
}
Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
So this assembly is built against .NET 8, not .NET Framework.
C++ code (cpp_project.dll) :
extern "C" __declspec(dllexport) int __stdcall ManagedAdd(int a, int b)
{
// Path to runtimeconfig.json
fs::path runtimeconfig = L"C:\\POC\\cs_core.runtimeconfig.json";
if (!init_dotnet(runtimeconfig.c_str()))
return -1;
if (!get_managed_add_fn(L"C:\\POC\\cs_core.dll",
L"MyNamespace.ManagedExports, cs_core",
L"Add"))
return -2;
return g_add(a, b);
}
VBA code (Excel) :
Private Declare PtrSafe Function ManagedAdd Lib "C:\POC\cpp_project.dll" _
(ByVal a As Long, ByVal b As Long) As Long
Sub TestManagedAdd()
MsgBox "Result = " & ManagedAdd(2, 3)
End Sub
The issue
When called from Excel, the DLL loads and unloads immediately. In Visual Studio debug output, I see:
'EXCEL.EXE' (Win32): Loaded 'C:\POC\cpp_project.dll'. Symbols loaded.
'EXCEL.EXE' (Win32): Unloaded 'C:\POC\cpp_project.dll'
But the expected C# code never runs, and no MessageBox/trace from DllMain shows up.
Also, Dependency Walker shows strange dependencies:
- cs_core.dll (net8.0) still appears to reference mscoree.dll and System.Runtime.dll from .NET Framework v4.0.30319, which is confusing.
Running corflags on cs_core.dll reports:
'EXCEL.EXE' (Win32): Loaded 'C:\POC\cpp_project.dll'. Symbols loaded.
'EXCEL.EXE' (Win32): Unloaded 'C:\POC\cpp_project.dll'
But the expected C# code never runs, and no MessageBox/trace from DllMain shows up.
Also, Dependency Walker shows strange dependencies:
cs_core.dll (net8.0) still appears to reference mscoree.dll and System.Runtime.dll from .NET Framework v4.0.30319, which is confusing.
Running corflags on cs_core.dll reports:
Version : v4.0.30319
CLR Header: 2.5
PE : PE32
ILONLY : 1
ven though it was compiled with net8.0.
What I tried
Using dotnet exec cs_core.dll → fails with MissingMethodException: Entry point not found, which makes sense since it’s not an EXE.
Ensured cs_core.runtimeconfig.json is present next to the DLL.
Tried different .NET SDK versions (8.0.414, 9.0.304).
Added logging in DllMain with OutputDebugString → never triggered from Excel.
Checked with Dependency Walker (x64) → shows .NET Framework dependencies, even for net8.0 build.
Question
What is the correct way to wire Excel VBA → native C++ DLL → .NET Core 8 DLL ?
Environment
- Windows 10 (x64)
- Excel 2016 (x64)
- Visual Studio 2022 (17.14)
- .NET SDK 8.0.414 and 9.0.304 installed
- .NET runtimes up to 9.0.8 installed
Would appreciate any help — we spent several days on this, and we are stuck at this “DLL loads/unloads immediately” stage.
load C# core (8.0) dll in C++ (20) dll