ExcelDna icon indicating copy to clipboard operation
ExcelDna copied to clipboard

Assembly Loading Issue: System.Runtime.CompilerServices.Unsafe Version Conflict with CommunityToolkit.Mvvm

Open yangf85 opened this issue 7 months ago • 10 comments

Problem Summary

When using CommunityToolkit.Mvvm 8.4.0 in an Excel-DNA add-in targeting .NET Framework 4.8, I encounter a persistent System.IO.FileLoadException related to System.Runtime.CompilerServices.Unsafe version conflicts. The issue appears to be specific to the Excel-DNA hosting environment.

Environment Details

  • Excel-DNA Version: 1.8.0
  • Target Framework: .NET Framework 4.8
  • Project SDK: Microsoft.NET.Sdk (modern SDK-style project)
  • CommunityToolkit.Mvvm: 8.4.0
  • Excel Version: Microsoft Excel (Office 365)
  • Operating System: Windows 10/11

Error Details

Exception Information

System.IO.FileLoadException: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=6.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.  
The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Source: CommunityToolkit.Mvvm
StackTrace:
  at CommunityToolkit.Mvvm.Messaging.WeakReferenceMessenger.Register[TMessage,TToken](Object recipient, TToken token, MessageHandlerDispatcher dispatcher)
  at CommunityToolkit.Mvvm.Messaging.WeakReferenceMessenger.Register[TMessage,TToken](IRecipient`1 recipient, TToken token)
  at CommunityToolkit.Mvvm.Messaging.IMessengerExtensions.Register[TMessage](IMessenger messenger, IRecipient`1 recipient)

Inner Exception:
FileLoadException: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.

Key Observations

  1. Version Mismatch: The outer exception requests v6.1.0.0, but inner exception shows v6.0.0.0 is being sought
  2. Correct Assembly Present: System.Runtime.CompilerServices.Unsafe.dll v6.1.0.0 exists in the output directory
  3. Excel-DNA Specific: Same code works fine in regular .NET applications
  4. Timing: Exception occurs during first call to WeakReferenceMessenger.Default.Register<T>()

Project Configuration

.csproj File

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
    <LangVersion>preview</LangVersion>
    <UseWPF>true</UseWPF>
    <UseWindowsForms>true</UseWindowsForms>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
    <PackageReference Include="ExcelDna.AddIn" Version="1.8.0" />
    <PackageReference Include="ExcelDna.Integration" Version="1.8.0" />
    <PackageReference Include="ExcelDna.IntelliSense" Version="1.8.0" />
    <PackageReference Include="ExcelDna.Interop" Version="15.0.1" />
    <PackageReference Include="ExcelDna.Registration" Version="1.8.0" />
    <!-- Other packages... -->
  </ItemGroup>
</Project>

App.config with Binding Redirects

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.0" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe"
                          publicKeyToken="b03f5f7f11d50a3a"
                          culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.1.0.0" newVersion="6.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Memory"
                          publicKeyToken="cc7b13ffcd2ddd51"
                          culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.1.3" newVersion="4.0.1.3" />
      </dependentAssembly>
      <!-- Other binding redirects... -->
    </assemblyBinding>
  </runtime>
</configuration>

Excel Add-in Code

[ExcelAddIn]
public class ExcelAddIn : IExcelAddIn
{
    public void AutoOpen()
    {
        // Initialization code that eventually leads to the error
        InitializeViewModels();
    }
}

public class OrderManageViewModel
{
    public OrderManageViewModel(IDataService data)
    {
        // This line consistently throws the FileLoadException
        WeakReferenceMessenger.Default.Register<string>(this);
    }
}

Troubleshooting Attempts

1. Assembly Verification

# Verified actual DLL versions in output directory
Get-ChildItem bin\*.dll | ForEach-Object { 
    [System.Reflection.AssemblyName]::GetAssemblyName($_.FullName).Version 
}
# Result: System.Runtime.CompilerServices.Unsafe.dll shows version 6.1.0.0

2. Custom Assembly Resolution

// Attempted various custom AssemblyResolve handlers
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    if (args.Name.StartsWith("System.Runtime.CompilerServices.Unsafe"))
    {
        var assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, 
            "System.Runtime.CompilerServices.Unsafe.dll");
        return Assembly.LoadFrom(assemblyPath); // Still fails with same error
    }
    return null;
};

3. Excel-DNA ExternalLibrary Configuration

Attempted to include dependencies in .dna file:

<DnaLibrary Name="MyAddIn" RuntimeVersion="v4.0">
  <ExternalLibrary Path="System.Runtime.CompilerServices.Unsafe.dll" 
                   LoadFromBytes="true" Pack="true" />
  <ExternalLibrary Path="CommunityToolkit.Mvvm.dll" 
                   LoadFromBytes="true" Pack="true" />
</DnaLibrary>

4. Alternative Loading Strategies

// Tried preloading assemblies using different methods:
Assembly.LoadFrom(path);           // FileLoadException
Assembly.LoadFile(path);          // StackOverflow (recursive calls)
Assembly.Load(File.ReadAllBytes(path)); // Still FileLoadException

Analysis and Questions

Excel-DNA Specific Concerns

  1. Assembly Loading Context: Does Excel-DNA create a separate assembly loading context that might interfere with binding redirects?

  2. COM Interop Impact: Could the COM interop nature of Excel add-ins affect how .NET Core dependencies are resolved?

  3. AppDomain Isolation: Are there multiple AppDomains involved that might cause assembly resolution issues?

  4. Timing Issues: Could there be a timing issue where binding redirects aren't applied before CommunityToolkit.Mvvm attempts to load its dependencies?

Questions for Excel-DNA Team

  1. Known Compatibility Issues: Are there known issues with modern NuGet packages that have complex dependency chains in Excel-DNA?

  2. Recommended Patterns: What's the recommended approach for handling modern .NET libraries with multiple transitive dependencies?

  3. Assembly Loading Best Practices: Are there Excel-DNA specific best practices for managing assembly loading in .NET Framework 4.8 projects?

  4. Debugging Tools: Are there Excel-DNA specific tools or techniques for diagnosing assembly loading issues?

Temporary Workarounds Attempted

1. Version Downgrade

<!-- Tried using older compatible versions -->
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<!-- Still encounters similar issues -->

2. Manual DLL Management

  • Manually copied specific versions of System.Runtime.CompilerServices.Unsafe.dll
  • Tried placing assemblies in different directories (bin, root, etc.)
  • Verified file permissions and integrity

Expected Behavior

The Excel-DNA add-in should be able to use modern NuGet packages like CommunityToolkit.Mvvm without assembly loading conflicts, similar to how they work in regular .NET applications.

Actual Behavior

Consistent FileLoadException when attempting to use CommunityToolkit.Mvvm functionality, specifically the WeakReferenceMessenger component.

Impact

This issue prevents the use of modern MVVM patterns and libraries in Excel-DNA add-ins, limiting development to older patterns and potentially forcing developers to implement custom solutions for functionality that should be available through well-maintained community libraries.

Additional Context

  • The same project configuration works perfectly in WPF applications
  • The issue is reproducible across different development machines
  • Multiple versions of Excel (2019, 365) exhibit the same problem
  • The issue persists regardless of Excel-DNA packing options

Request

Could the Excel-DNA team provide guidance on:

  1. Root Cause: What aspect of Excel-DNA's assembly loading mechanism might be causing this version conflict?

  2. Recommended Solution: What's the preferred approach for resolving modern NuGet package dependencies in Excel-DNA add-ins?

  3. Future Support: Are there plans to improve compatibility with modern .NET ecosystem packages?

Any insights, workarounds, or potential fixes would be greatly appreciated. This functionality is crucial for maintaining modern development practices in Excel add-in development.

yangf85 avatar May 26 '25 07:05 yangf85

Please retest this with the latest pre-release version of Excel-DNA (NuGet package version 1.9.0-beta2).

govert avatar May 26 '25 16:05 govert

请使用 Excel-DNA 的最新预发布版本(NuGet 包版本 1.9.0-beta2)重新测试此内容。

Hi, I'm experiencing an assembly version resolution issue after upgrading to ExcelDNA 1.9.0-beta. The application is unable to locate the correct assembly version at runtime. Steps to reproduce:

Upgraded ExcelDNA from stable version to 1.9.0-beta Updated all related package references Rebuilt the project successfully Runtime error occurs when Excel tries to load the add-in

Expected behavior: The add-in should load correctly with the new beta version. Actual behavior: Assembly version mismatch error - the system is still looking for the previous version assemblies. Environment:

Workaround attempts: Clean and rebuild solution Clear NuGet package cache Restart Visual Studio and Excel

Image

yangf85 avatar May 27 '25 07:05 yangf85

I've created a minimal reproduction solution to demonstrate this assembly version issue:

ExcelWithMvvm.zip

yangf85 avatar May 27 '25 07:05 yangf85

I am not able to reproduce the issue from your ExcelWithMvvm solution.

Your project is targeting both .NET Framework 4.8 and .NET 8, and both targets work as expected for me when pressing the ribbon button. Are you seeing the exception with both target frameworks, or only when testing one of the two?

Please check if you delete the bin and obj directories before rebuilding, whether you still get the exception. Sometimes an old file there can confuse things.

For the .NET Framework 4.8 output, this is what I see in the output directory.

Image

Perhaps this discussion can help you Nick Craver - Binding Redirects . If your problem is with the .NET Framework target, then sometimes adding <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> can help you see more about the expected bindings. But in this project it does not seem to have an effect.

You can also experiment by setting <AutoUnifyAssemblyReferences>false</AutoUnifyAssemblyReferences> (with <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>) which should show you at build time what the assembly version conflicts are.

Finally, to debug assembly loading for .NET Framework at runtime, there is the Fusion Logging option (https://learn.microsoft.com/en-us/dotnet/framework/tools/fuslogvw-exe-assembly-binding-log-viewer).

govert avatar May 27 '25 08:05 govert

@govert

When I changed the target framework of the project file to .NET 8.0 (Windows-only), the line WeakReferenceMessenger.Default.Register(this); in the ExcelWithMvvm project started working correctly. This leads me to suspect that there might be a conflict between the .NET Framework 4.8 and CommunityToolkit.Mvvm.

yangf85 avatar May 27 '25 12:05 yangf85

On my machine it works fine with no error for both .NET Framework 4.8 and .NET 8.

govert avatar May 27 '25 12:05 govert

This is truly a heartbreaking story, and I can’t find any reason for this issue.

yangf85 avatar May 27 '25 13:05 yangf85

The add-in in your .zip file ExcelWithMvvm\ExcelWithMvvm\bin\Debug\net48\ExcelWithMvvm-AddIn64.xll" works fine (I can press the button with no error). So, it works with .NET Framework 4.8 on my machine. If you just run that add-in and go to the ribbon and press the button, do you have an error? If so, I suggest you look at getting the Fusion logging to work, to see whether you have a file in the GAC that causes trouble. Otherwise, I can't see why it would be different on my machine and yours. Perhaps you see problems in a bigger project, but not with .NET Framework 4.8 on the small project?

govert avatar May 27 '25 18:05 govert

@govert Hi.

"I have enabled the binding log as you instructed, but as a beginner, I'm having trouble understanding these logs. Could you help me analyze them? I've uploaded the log file."

Let me know if you need further adjustments!

ExcelWithMvvm.zip Logs.zip

yangf85 avatar May 28 '25 13:05 yangf85

Image

The final solution is to modify the redirection of the following two DLLs as shown below, which allows the message service to run normally. However, only basic testing has been conducted, so it is uncertain whether other issues may still exist. Updates will be provided if further developments arise.

yangf85 avatar Jun 05 '25 12:06 yangf85