.NET Core 应用程序和 System.Reflection.Assembly.LoadFrom(...) 是否存在特定问题?

Are there specific issues with .NET Core apps and System.Reflection.Assembly.LoadFrom(...)?

我正在使用我编写的工具调用以下行以检查一些内容,包括程序集版本:

var assm = System.Reflection.Assembly.LoadFrom(path);

该工具按设计工作,除非我尝试 运行 它针对 .NET Core 应用程序。

当我提供为 .NET Core 3.1、5.0 或 6.0 编译的应用程序的路径时,我在尝试加载程序集时收到 System.BadImageFormatException

我的工具是使用 .NET 4.7.2 Framework 用 C# 编写的,我将其更新为使用 4.8,但仍然出现异常。认为这可能是常规 .NET 和 .NET Core 之间的混淆,我编写了以下快速项目并使用与目标应用程序 (.NET Core) 相同的框架对其进行了编译,但我得到了完全相同的错误。

事实证明,它会为所有 .NET Core 应用程序抛出异常。它在使用 .NET 4.7.2 Framework 等的典型 Windows 应用程序上运行正常,但在任何 .NET Core 应用程序上都会死机。

在对此进行研究时,我还没有发现任何迹象表明 .NET Core 应用程序清单是如此不同,以至于它们会导致此调用阻塞。我所有的应用程序和测试都编译为 64 位应用程序;没有混合使用 64 位和 32 位。

使用简单测试器应用重现的步骤(如下):

  1. 打开你的味道Visual Studio
  2. 创建一个新的控制台应用程序项目
  3. 在模板字段中,分别输入:C#、Windows 和控制台
  4. Select 'Console App'(不是: 控制台应用程序(.NET 框架))
  5. 点击下一步
  6. 为您的应用起一个简称,然后单击下一步
  7. 选择 .NET core 5(或 3.1 或 6 - 但您需要删除 6.0 的 main{})
  8. 粘贴下面的代码并编译。
  9. 提供此应用程序(或任何其他 .Net 核心应用程序)的路径
  10. 挠头

简单测试仪:

internal class Program
{
    static void Main(string[] args)
    {
        Console.Write("\r\nEnter complete path to assembly:");
        var path = Console.ReadLine();
        if (!string.IsNullOrEmpty(path))
        {
            var assm = System.Reflection.Assembly.LoadFrom(path);

            if (assm != null)
            {
                var c = assm.GetCustomAttributes(false);
                if (null != c && c.Length > 0)
                {
                    Console.WriteLine($"Len:{c.Length} Value type:{c}");
                    Console.WriteLine($"c0:[{c[0]}]");
                    var x = 1; // convenient breakpoint to examine vars
                }
            }
        }

        Console.WriteLine("Complete...");
        Console.ReadLine();
    }
}

更新:

对于现在或以后阅读本文的任何人,Microsoft 提供了一个用于读取跨体系结构 .NET 程序集属性的新包:System.Reflection.MetadataLoadContext - 在 Nuget.org

上可用

从 .NET Core 开始(我不记得到底是哪个 .NET Core 版本),使用默认设置构建 application/executable 项目时生成的可执行 .exe 文件不再是 .NET 程序集就像过去的 .NET Framework 一样。

相反,.NET 程序被编译成单独的程序集 DLL(称为“cross-platform binary"; the associated exe file is called "platform-specific executable”)。因此,与 .NET Framework 应用程序不同,您需要找到并加载包含应用程序代码的程序集 DLL。造成这种差异的原因基本上归结为旧的 .NET Framework 是一个 Windows-only 平台(其他兼容平台如 Mono 无法承受),而 .NET Core(以及 .NET 5/6/7/. ..) 非常强调 cross-platform。

(顺便说一句,也可以将项目构建为单个文件部署,在这种情况下,您将找不到单独的 .exe 和 .dll 文件。)