.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 位。
使用简单测试器应用重现的步骤(如下):
- 打开你的味道Visual Studio
- 创建一个新的控制台应用程序项目
- 在模板字段中,分别输入:C#、Windows 和控制台
- Select 'Console App'(不是: 控制台应用程序(.NET 框架))
- 点击下一步
- 为您的应用起一个简称,然后单击下一步
- 选择 .NET core 5(或 3.1 或 6 - 但您需要删除 6.0 的 main{})
- 粘贴下面的代码并编译。
- 提供此应用程序(或任何其他 .Net 核心应用程序)的路径
- 挠头
简单测试仪:
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 文件。)
我正在使用我编写的工具调用以下行以检查一些内容,包括程序集版本:
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 位。
使用简单测试器应用重现的步骤(如下):
- 打开你的味道Visual Studio
- 创建一个新的控制台应用程序项目
- 在模板字段中,分别输入:C#、Windows 和控制台
- Select 'Console App'(不是: 控制台应用程序(.NET 框架))
- 点击下一步
- 为您的应用起一个简称,然后单击下一步
- 选择 .NET core 5(或 3.1 或 6 - 但您需要删除 6.0 的 main{})
- 粘贴下面的代码并编译。
- 提供此应用程序(或任何其他 .Net 核心应用程序)的路径
- 挠头
简单测试仪:
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 文件。)