在自包含的 .Net Core Web 应用 运行 中作为 Windows 服务引用嵌套 DLL 的问题
Issue with nested DLL referencing in a self-contained .Net Core web app running as a Windows service
错误
首先,让我们从错误消息开始:
System.BadImageFormatException: 'Could not load file or assembly 'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (0x80131058)'
根据我的经验,如果 DLL 丢失或不在预期范围内,通常会出现此类错误 format/version。但是,我不知道我需要做什么来解决这个错误。
设置
主要项目是 ASP.Net Core 3.1 应用程序。
它被配置为能够 运行 作为 Window 服务并支持 Web API 和 MVC 框架。所以我的 Program.cs 看起来像这样:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var builder = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
builder.UseWindowsService();
return builder;
}
}
那部分工作得很好,我可以 运行 应用程序作为 Windows 服务并提供剃须刀视图和 Web API 端点等
但是,此解决方案中的项目较多。我有几个由服务应用程序引用的 .Net 4.6 class 库项目。所以我的解决方案看起来像这样:
- 服务应用程序 (NET CORE 3.1)
- 库 1 (NET 4.6)
- 库 2 (NET 4.6)
服务应用程序引用库 1,库 1 引用库 2。
这两个库中的任何一个代码都可以正常工作并且可以被服务应用程序使用。
问题是库 2 引用了 System.Management DLL,这就是导致错误的原因。每当我使用使用该 DLL 的函数时,都会出现上述错误。
到目前为止的尝试
到目前为止我的尝试包括:
- 将 DLL 设置为“复制到输出”
- 将 DLL 引用直接添加到 Web 服务应用程序
- 正在手动将 DLL 复制到输出文件夹。调试和发布文件夹(注意:发布设置为“自包含”应用程序)
问题
基本上,我该如何解决这个问题?或者至少,我怎样才能进一步调试问题以找到可能的解决方案。
我当时无法重现,但我怀疑这是使用 dotnet publish
的自包含发布过程解决传递依赖性的方式中的错误。
重点是,您的 .NET Core 3.1 应用程序 doesn't run on .NET Framework,而您引用的库称为“Lib 2”。
并且您的 Lib 2 引用了 NuGet 包 System.Management,当安装在针对 .NET Framework 的项目上时...除了让您的项目引用 .NET Framework 参考程序集外什么都不做System.Management
,在 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1
中找到。在 运行 时,.NET Framework 将从 GAC 加载适当的程序集,但 .NET Core 运行 时不会这样做。
现在,在发布您的 .NET Core 应用程序时,MSBuild 遍历要复制的依赖项,并且(我想再次)查看参考程序集并 “我想要那个!”。 =32=] 并将其复制到您的输出目录。
但是您不能 运行 引用程序集,您只能引用它们,所以在 运行 时,您的应用程序崩溃并出现异常,具体说明:
Reference assemblies should not be loaded for execution
一种解决方法(但绝对不是解决方案)是从您的 .NET Core 应用程序中引用相同的 System.Management 包,其中该包实际上将提取包含 运行 可用代码的 DLL,并且那一个 将被复制到您的输出目录。但这可能会导致其他问题,例如 DLL 在构建期间被引用覆盖。
我建议查看 GitHub 这是一个已知问题,还是由您的项目设置引起的问题。
错误
首先,让我们从错误消息开始:
System.BadImageFormatException: 'Could not load file or assembly 'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (0x80131058)'
根据我的经验,如果 DLL 丢失或不在预期范围内,通常会出现此类错误 format/version。但是,我不知道我需要做什么来解决这个错误。
设置
主要项目是 ASP.Net Core 3.1 应用程序。
它被配置为能够 运行 作为 Window 服务并支持 Web API 和 MVC 框架。所以我的 Program.cs 看起来像这样:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var builder = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
builder.UseWindowsService();
return builder;
}
}
那部分工作得很好,我可以 运行 应用程序作为 Windows 服务并提供剃须刀视图和 Web API 端点等
但是,此解决方案中的项目较多。我有几个由服务应用程序引用的 .Net 4.6 class 库项目。所以我的解决方案看起来像这样:
- 服务应用程序 (NET CORE 3.1)
- 库 1 (NET 4.6)
- 库 2 (NET 4.6)
服务应用程序引用库 1,库 1 引用库 2。
这两个库中的任何一个代码都可以正常工作并且可以被服务应用程序使用。
问题是库 2 引用了 System.Management DLL,这就是导致错误的原因。每当我使用使用该 DLL 的函数时,都会出现上述错误。
到目前为止的尝试
到目前为止我的尝试包括:
- 将 DLL 设置为“复制到输出”
- 将 DLL 引用直接添加到 Web 服务应用程序
- 正在手动将 DLL 复制到输出文件夹。调试和发布文件夹(注意:发布设置为“自包含”应用程序)
问题
基本上,我该如何解决这个问题?或者至少,我怎样才能进一步调试问题以找到可能的解决方案。
我当时无法重现,但我怀疑这是使用 dotnet publish
的自包含发布过程解决传递依赖性的方式中的错误。
重点是,您的 .NET Core 3.1 应用程序 doesn't run on .NET Framework,而您引用的库称为“Lib 2”。
并且您的 Lib 2 引用了 NuGet 包 System.Management,当安装在针对 .NET Framework 的项目上时...除了让您的项目引用 .NET Framework 参考程序集外什么都不做System.Management
,在 C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1
中找到。在 运行 时,.NET Framework 将从 GAC 加载适当的程序集,但 .NET Core 运行 时不会这样做。
现在,在发布您的 .NET Core 应用程序时,MSBuild 遍历要复制的依赖项,并且(我想再次)查看参考程序集并 “我想要那个!”。 =32=] 并将其复制到您的输出目录。
但是您不能 运行 引用程序集,您只能引用它们,所以在 运行 时,您的应用程序崩溃并出现异常,具体说明:
Reference assemblies should not be loaded for execution
一种解决方法(但绝对不是解决方案)是从您的 .NET Core 应用程序中引用相同的 System.Management 包,其中该包实际上将提取包含 运行 可用代码的 DLL,并且那一个 将被复制到您的输出目录。但这可能会导致其他问题,例如 DLL 在构建期间被引用覆盖。
我建议查看 GitHub 这是一个已知问题,还是由您的项目设置引起的问题。