Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assembly.Load(String) should throw BadImageFormatException instead of FileNotFoundException when loading non-CLR Assembly #111597

Open
HenryZhang-ZHY opened this issue Jan 20, 2025 · 3 comments
Labels
area-AssemblyLoader-coreclr untriaged New issue has not been triaged by the area owner

Comments

@HenryZhang-ZHY
Copy link

HenryZhang-ZHY commented Jan 20, 2025

Description

It should throw System.BadImageFormatException when loading a non-CLR Assembly with Assembly.Load(String), e.g.: Microsoft.Data.SqlClient.SNI.dll.
net48 program has the correct behavior, but the net8.0 program doesn't, which is different from the official document description.

Reproduction Steps

reproduce-dotnet-runtime-issue-111597

Expected behavior

Unhandled Exception: System.BadImageFormatException: Could not load file or assembly 'Microsoft.Data.SqlClient.SNI' or one of its dependencies. The module was expected to contain an assembly manifest.

Actual behavior

Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Data.SqlClient.SNI, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

Regression?

No response

Known Workarounds

AssemblyName.GetAssemblyName(String) works correctly in net8.0.

    /// <summary>
    /// Load an assembly from the given path.
    /// The assembly might not be a CLR assembly, e.g. Microsoft.Data.SqlClient.SNI.dll. But Assembly.Load doesn't throw BadImageFormatException, instead it throws FileNotFoundException, which can lead to confusion.
    /// So we use AssemblyName.GetAssemblyName to check if the assembly is a CLR assembly.
    /// </summary>
    /// <param name="assemblyPath">absolute path to the assembly</param>
    /// <returns>null if the assembly is not a CLR assembly; otherwise, the Assembly object.</returns>
    static Assembly? LoadAssembly(string assemblyPath)
    {
      AssemblyName? assemblyName = null;
      try
      {
        assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
      }
      catch (BadImageFormatException)
      {
      }

      return assemblyName is null ? null : Assembly.Load(assemblyName);
    }

Configuration

No response

Other information

No response

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Jan 20, 2025
Copy link
Contributor

Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov
See info in area-owners.md if you want to be subscribed.

@jkotas
Copy link
Member

jkotas commented Jan 20, 2025

.NET Core assembly loader does not consider files that were manually copied into the application directory as application assemblies. It only considers files that the app has been composed from during the build - the list is in .deps.json file in the app directory. This behavior is different from .NET Framework by design.

It explains why you see FileNotFoundException in your repro project that is manually copying Microsoft.Data.SqlClient.SNI.dll into the application directory.

@HenryZhang-ZHY
Copy link
Author

My repo is a simplified reproduction.
In real world, it still throws FileNotFoundException even .deps.json contains the Microsoft.Data.SqlClient.SNI.dll.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-AssemblyLoader-coreclr untriaged New issue has not been triaged by the area owner
Projects
Status: No status
Development

No branches or pull requests

2 participants