Hi Keith,
Excel-DNA creates an AssemblyLoadContext for your add-in, and should be loading assemblies according to the .deps.json file of your library.
But for assemblies that are part of the runtime (like System.Net.Http) I think the ALC load will always use the runtime version and not a newer version that you ship.
You might try some diagnostics like this at different places in your code:
using System;
using System.Reflection;
using System.Runtime.Loader;
public static class AssemblyTrace
{
public static void Dump()
{
var asm = typeof(System.Net.Http.HttpClient).Assembly;
Console.WriteLine("=== System.Net.Http Assembly Info ===");
Console.WriteLine("FullName: " + asm.FullName);
Console.WriteLine("Location: " + asm.Location);
Console.WriteLine("From GAC: " + (asm.GlobalAssemblyCache ? "yes" : "no"));
Console.WriteLine("LoadCtx: " + AssemblyLoadContext.GetLoadContext(asm)?.GetType().FullName);
Console.WriteLine("=====================================");
}
}
I'd call it in AutoOpen() before your code runs, and also after your code, and see whether you find which version is being loaded from where.
If the assembly in question is not System.Net.Http then try others.
You can also look in the .deps.json file to see what the intended assemblies are.
You're looking for evidence that it loads an old version from the runtime instead of the new version from your add-in output.
If so, your only way forward is to upgrade your runtime target or downgrade that assembly reference.
If that's not what is going on, I think another problem might be that the transitive dependencies don't end up with the right version of the extra assemblies. So your .deps.json is basically inconsistent - the add-in's assembly references end up loading an older version of something. If this is the case, you can try to explicitly add PackageReference to some of the transitive dependencies, forcing the newer version of these.
ChatGPT suggested the code below to explore the loaded versions further (I didn't try it).
-Govert
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Collections.Generic;
public static class DependencyDiagnostics
{
// Assemblies whose version must be consistent (transitive closure)
static readonly string[] InterestPrefixes = new[]
{
"Microsoft.Extensions.",
"System.Diagnostics.DiagnosticSource",
"System.Diagnostics.Metrics",
"System.Net.Http",
"Microsoft.Bcl.AsyncInterfaces"
};
public static void Dump()
{
Console.WriteLine("=== BEGIN EXCEL-DNA DEPENDENCY DIAGNOSTICS ===");
var loaded = AppDomain.CurrentDomain.GetAssemblies();
var relevant = loaded
.Where(a =>
InterestPrefixes.Any(p =>
a.GetName().Name.StartsWith(p, StringComparison.OrdinalIgnoreCase)))
.OrderBy(a => a.GetName().Name)
.ToList();
foreach (var asm in relevant)
{
WriteAsm(asm);
}
Console.WriteLine();
Console.WriteLine("=== VERSION GROUPS ===");
ReportVersionGroups(relevant);
Console.WriteLine("=== END EXCEL-DNA DEPENDENCY DIAGNOSTICS ===");
}
static void WriteAsm(Assembly asm)
{
var name = asm.GetName();
var ctx = AssemblyLoadContext.GetLoadContext(asm);
var location = asm.IsDynamic ? "<dynamic>" : (string.IsNullOrEmpty(asm.Location) ? "<unknown>" : asm.Location);
Console.WriteLine($"{name.Name,-45} {name.Version,-15} {ctx?.GetType().Name,-25} {location}");
}
static void ReportVersionGroups(List<Assembly> asms)
{
// Group by simple name (Microsoft.Extensions.Http → group)
var groups = asms.GroupBy(a => a.GetName().Name);
foreach (var g in groups)
{
var versions = g.Select(a => a.GetName().Version).Distinct().ToList();
if (versions.Count > 1)
{
Console.WriteLine($"WARNING: {g.Key} loaded multiple versions: {string.Join(", ", versions)}");
foreach (var asm in g)
{
WriteAsm(asm);
}
Console.WriteLine();
}
}
}
}