简体   繁体   English

无法为 NET Standard 加载 NuGet 包的文件或程序集异常 NET 5/6

[英]could not load file or assembly exception NET 5/6 of NuGet package for NET Standard

I'm at the end of my rope trying to figure out why my working DLL cannot load a NuGet package that it could always load before (like for a whole year).我已经走到了尽头,试图弄清楚为什么我的工作 DLL 无法加载它之前总是可以加载的 NuGet 包(比如一整年)。 My system has 70 NET 6 projects and half a dozen of them use the same NuGet package to read XML files.我的系统有 70 个 NET 6 项目,其中有六个使用同一个 NuGet 包来读取 XML 文件。 Recently (a few months ago) I upgraded everything to NET 6, and even after that upgrade, everything worked fine.最近(几个月前)我将所有东西都升级到了 NET 6,即使在升级之后,一切都运行良好。

But now, one of my C# class libraries generates an exception in a constructor because it can't find the NuGet package that sits right beside it in the filesystem app folder where everything is loaded from.但是现在,我的一个 C# 类库在构造函数中生成了一个异常,因为它在加载所有内容的文件系统应用程序文件夹中找不到位于它旁边的 NuGet 包。 The error message was:错误消息是:

.ctor Could not load file or assembly xxx blah blah. The system could not find the file specified.

For what it is worth, here is a trace of the build options in the batch file that I have been using for months.对于它的价值,这里是我使用了几个月的批处理文件中的构建选项的跟踪。

Deleting hscore\hscore\bin Deleting hscore\hscore\obj Deleting hscore\hscore\packages "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\msbuild.exe" -nologo -m -V:minimal -t:clean;restore;publish /p:Platform=AnyCPU /p:PlatformTarget=AnyCPU /p:Configuration=Debug /p:TargetFramework=net6.0-windows7.0 /p:RuntimeIdentifier=win-x64 /p:SelfContained=false /p:PublishProtcol=FileSystem /p:DeleteExistingFiles=true /p:PublishDir=c:\dev\holding\core.plt -nowarn:MSB3305 c:\dev\products\hscore\hscore\hscore.csproj删除 hscore\hscore\bin 删除 hscore\hscore\obj 删除 hscore\hscore\packages "C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\msbuild.exe" -nologo -m -V:最小 -t:clean;restore;publish /p:Platform=AnyCPU /p:PlatformTarget=AnyCPU /p:Configuration=Debug /p:TargetFramework=net6.0-windows7.0 /p:RuntimeIdentifier=win-x64 /p: SelfContained=false /p:PublishProtcol=FileSystem /p:DeleteExistingFiles=true /p:PublishDir=c:\dev\holding\core.plt -nowarn:MSB3305 c:\dev\products\hscore\hscore\hscore.csproj

Determining projects to restore... Restored c:\dev\products\hscore\hscore\hscore.csproj (in 874 ms).确定要恢复的项目... 已恢复 c:\dev\products\hscore\hscore\hscore.csproj(在 874 毫秒内)。 hscore -> c:\dev\products\hscore\hscore\bin\Debug\net6.0-windows7.0\win-x64\hscore.dll hscore -> c:\dev\holding\core.plt\ hscore -> c:\dev\products\hscore\hscore\bin\Debug\net6.0-windows7.0\win-x64\hscore.dll hscore -> c:\dev\holding\core.plt\

I have done the following to debug it, without success:我做了以下调试,但没有成功:

  • deleted the bin/obj folders of the failing class library删除了失败类库的 bin/obj 文件夹

  • checked the target framework of all projects (= net6.0-windows7.0)检查所有项目的目标框架(= net6.0-windows7.0)

  • checked the runtime identifier of all projects (= win-x64)检查所有项目的运行时标识符 (= win-x64)

  • checked the build configuration (Debug, AnyCPU)检查构建配置(调试,AnyCPU)

  • removed and re-added the NuGet package (with a specific version)删除并重新添加了 NuGet 包(具有特定版本)

  • the Nuget package depends on NET Standard, compatible with NET 6 Nuget 包依赖于 NET Standard,与 NET 6 兼容

  • and I use the same version in other NET 6 programs that are working fine我在其他运行良好的 NET 6 程序中使用相同的版本

  • restored and rebuilt the DLL恢复并重建 DLL

  • published it to the destination folder where it is run from将其发布到运行它的目标文件夹

  • checked that the expected Nuget package is there (it was)检查预期的 Nuget 包是否存在(它是)

  • and yet it still fails to find the Nuget package但它仍然无法找到 Nuget 包

  • I tried to trace DLL loads of the process with the SysInternals Process Monitor, but I am not good enough to do that (if it is even possible).我尝试使用 SysInternals Process Monitor 跟踪进程的 DLL 负载,但我还不足以做到这一点(如果可能的话)。 I can filter events to see the parent app process load, but the failing DLL is called by the parent process and I don't know how to see the search paths it is using to find the Nuget package.我可以过滤事件以查看父应用程序进程的加载,但失败的 DLL 由父进程调用,我不知道如何查看它用于查找 Nuget 包的搜索路径。

I want to believe that the problem is a version mismatch between NET 5 and NET 6 and the version of the Nuget package sitting in the folder, because I once had a problem like that.我想相信问题是 NET 5 和 NET 6 之间的版本不匹配以及位于文件夹中的 Nuget 包的版本,因为我曾经遇到过这样的问题。 For example, if I had a NET Framework version of the Nuget package, it would not be "found" by a NET 5 DLL that wanted to load it.例如,如果我有 Nuget 包的 NET Framework 版本,想要加载它的 NET 5 DLL 将不会“找到”它。 (I am NOT saying that is my problem, because I have no NET Framework projects anymore.) (我并不是说这是我的问题,因为我不再有 NET Framework 项目。)

The most recent thing I have been working on is the build system and options.我最近一直在做的事情是构建系统和选项。 I can build the whole system with batch files or with parallel builds (when the system is working).我可以使用批处理文件或并行构建(当系统工作时)构建整个系统。 I use the same msbuild options in both cases, and the batch method has been reliable and shows no build errors, no publish errors, all the correct build options, and no warnings or errors whatsoever.我在这两种情况下都使用了相同的 msbuild 选项,并且批处理方法很可靠,并且没有显示构建错误、没有发布错误、所有正确的构建选项,也没有任何警告或错误。

The Nuget package pulls in 10 or 20 dependencies, but that is all automatic, and the package works with other console programs and apps that are working fine. Nuget 包引入了 10 或 20 个依赖项,但这都是自动的,并且该包可以与其他运行良好的控制台程序和应用程序一起使用。 So, I don't think there is anything wrong with Nuget package.所以,我不认为 N​​uget 包有什么问题。 All the working apps use the same Nuget package from the same runtime folder.所有工作应用程序都使用相同运行时文件夹中的相同 Nuget 包。 I don't know why this one DLL is having a problem.我不知道为什么这个 DLL 有问题。 AND I have not changed anything in the failing DLL class library for months (and it has been working fine).并且几个月来我没有更改失败的 DLL 类库中的任何内容(并且它一直运行良好)。

Does anyone have suggestions on what else I might try to debug the problem and get the system working again?有没有人对我可能尝试调试问题并让系统再次运行有什么建议? Thank you.谢谢你。

UPDATE - New version and build, but still a runtime failure.更新 - 新版本和构建,但仍然是运行时失败。

Just to be sure, I upgraded the Nuget package that could not be found to the latest version and replaced all references in my 70 projects to the new version.为了确定,我将找不到的 Nuget 包升级到最新版本,并将我 70 个项目中的所有引用替换为新版本。 Then I rebuilt the system (no warnings, no errors).然后我重建了系统(没有警告,没有错误)。 But that did not make a difference.但这并没有什么不同。 Now the new version cannot be found.现在找不到新版本了。

All unit tests of the code in question work flawlessly in VStudio, presumably because VS loads the Nuget package properly.有问题的代码的所有单元测试在 VStudio 中都能完美运行,大概是因为 VS 正确加载了 Nuget 包。 I am mystified and would appreciate thoughts on how to proceed.我很困惑,并希望对如何进行的想法表示赞赏。 Thank you.谢谢你。

UPDATE 2 - installed 'dotnet-trace' and traced DLL loads更新 2 - 安装 'dotnet-trace' 并跟踪 DLL 加载

I found a page that described how to dotnet tool install --global dotnet-trace and then captured a trace of my app trying to find the elusive Nuget package that is sitting right beside the requesting DLL.我找到了一个描述如何dotnet tool install --global dotnet-trace的页面,然后捕获了我的应用程序的痕迹,该应用程序试图找到位于请求 DLL 旁边的难以捉摸的 Nuget 包。 Although I could my app loading various app DLLs (and tons of system DLLs) with found pathnames, the trace showed nothing useful about the Nuget package.尽管我的应用程序可以使用找到的路径名加载各种应用程序 DLL(以及大量系统 DLL),但跟踪显示 Nuget 包没有任何用处。

The trace entries show the system searching in stages FindInLoadContext, then ApplicationAssemblies, then AppDomainAssemblyResolveEvent.跟踪条目显示了系统在 FindInLoadContext、ApplicationAssemblies、AppDomainAssemblyResolveEvent 等阶段的搜索。 After that, the system throws an exception because it can't find the Nuget package.之后,系统因为找不到 Nuget 包而抛出异常。

I would have thought the system FindInLoadContext would find it in the same folder as the executing and requesting assemblies, but it seems not so.我原以为系统 FindInLoadContext 会在与执行和请求程序集相同的文件夹中找到它,但似乎并非如此。

Ideas?想法? I'm lost.我迷路了。 And everything used to work fine.过去一切都很好。

UPDATE 3 - A small console app calls the DLL and it finds the Nuget package更新 3 - 一个小型控制台应用程序调用 DLL 并找到 Nuget 包

The problem scenario in this question is: WindowsFormsApp -> loads MyCore.dll and calls new MyCore.MyObject() , which in the constructor tries to read some XML files using MyUtils.dll, which tries to reference the mystery Nuget package for reading XML files.这个问题的问题场景是: WindowsFormsApp -> 加载 MyCore.dll 并调用new MyCore.MyObject() ,它在构造函数中尝试使用 MyUtils.dll 读取一些 XML 文件,它试图引用神秘的 Nuget 包来读取 XML文件。 MyUtils.dll cannot find the package, no matter what I do.无论我做什么,MyUtils.dll 都找不到包。

I wrote a small console program to load MyUtils.dll and called the exact same MyUtils.ReadMyXmlFiles API to read the files.我编写了一个小型控制台程序来加载 MyUtils.dll 并调用完全相同的MyUtils.ReadMyXmlFiles API 来读取文件。 The console app (actually, the system assembly loader) correctly found the Nuget package and read the XML files properly.控制台应用程序(实际上是系统程序集加载器)正确找到了 Nuget 包并正确读取了 XML 文件。 This all occurred in the same folder that contains the Forms app and the Nuget package.这一切都发生在包含 Forms 应用程序和 Nuget 包的同一文件夹中。

The only difference now is that the WindowsForms app calls an intermediate DLL that calls a constructor that references MyUtils.dll.现在唯一的区别是 WindowsForms 应用程序调用了一个中间 DLL,该 DLL 调用了一个引用 MyUtils.dll 的构造函数。

Could the intermediate DLL + constructor call be changing the Assembly Load Context (FindInLoadContext search rules) for the Nuget package load operation?中间 DLL + 构造函数调用是否会更改 Nuget 包加载操作的程序集加载上下文(FindInLoadContext 搜索规则)? Very strange.很奇怪。

The overall problem was that my Windows Forms app failed during boot (in the Form_Load event) because a Nuget package could not be found to read some XML configuration files.总体问题是我的 Windows 窗体应用程序在启动期间失败(在 Form_Load 事件中),因为找不到 Nuget 包来读取某些 XML 配置文件。

Four assemblies were involved in the problem.该问题涉及四个组件。 Assembly1 (the app) called Assembly2 (.. new Assembly2Object()), whose constructor called an Assembly3 method (utilities.ReadXMLFile) which called Assembly4 (NugetPackage.XMLReader). Assembly1(应用程序)调用了 Assembly2 (..new Assembly2Object()),其构造函数调用了 Assembly3 方法 (utilities.ReadXMLFile),该方法调用了 Assembly4 (NugetPackage.XMLReader)。

You can see that only Assembly4 references the Nugetpackage which could not be found.您可以看到只有 Assembly4 引用了找不到的 Nugetpackage。 Normally, there should be no reason for Assemblies 1 or 2 to know about the existence of the NugetXmlReader used by Assembly3.通常,Assemblies 1 或 2 没有理由知道 Assembly3 使用的 NugetXmlReader 的存在。 But, the exceptions and assembly load traces of dotnet-trace and procmon clearly showed that Assembly3 (utilities.ReadXmlFile) could not find the NugetPackage at runtime, even though the right package was in the folder beside the executing assemblies (1->3).但是,dotnet-trace 和 procmon 的异常和程序集加载跟踪清楚地表明,Assembly3 (utilities.ReadXmlFile) 在运行时找不到 NugetPackage,即使正确的包位于正在执行的程序集旁边的文件夹中 (1->3) .

The "solution" for my case was to add a Nuget package dependency to Assembly1 (the WinFormsApp).我的情况的“解决方案”是将 Nuget 包依赖项添加到 Assembly1(WinFormsApp)。 As soon as I did that, Assembly3 (utilities.ReadXmlFile) could find Assembly4 (Nugetpackage).一旦我这样做了,Assembly3 (utilities.ReadXmlFile) 就可以找到 Assembly4 (Nugetpackage)。

My working theory is that during a WinForms boot sequence (including the Form_Shown event), the AssemblyLoadContext from Assembly1 is used to look up all assemblies in any call chain (like Assembly2 calling Assembly3 calling NugetPackage4).我的工作理论是,在 WinForms 启动序列(包括 Form_Shown 事件)期间,Assembly1 中的 AssemblyLoadContext 用于查找任何调用链中的所有程序集(如 Assembly2 调用 Assembly3 调用 NugetPackage4)。

Because the load context of Assembly1 has no reference to NugetPackage, and because the .deps.json file for Assembly1 is present (the doc says it is used to form the load context), Assembly3 - using the assembly load context for Assembly1 - could not find the NugetPackage.因为 Assembly1 的加载上下文没有对 NugetPackage 的引用,并且因为 Assembly1 的 .deps.json 文件存在(文档说它用于形成加载上下文),所以 Assembly3 - 使用 Assembly1 的程序集加载上下文 - 不能找到 NugetPackage。

When I added a dependency to Assembly4 (Nugetpackage) to Assembly1, then the assembly load context from Assembly1 was used by the System AssemblyLoader FindInLoadContext phase to search for (and find) the NugetPackage4 wanted by (the referencing assembly) Assembly3.当我将 Assembly4(Nugetpackage)的依赖项添加到 Assembly1 时,System AssemblyLoader FindInLoadContext 阶段使用来自 Assembly1 的程序集加载上下文来搜索(并找到)(引用程序集)Assembly3 想要的 NugetPackage4。

I used to think that each assembly in a calling chain would have its own assembly load context used by AssemblyLoad/FindInLoadContext.我曾经认为调用链中的每个程序集都有自己的程序集加载上下文,由 AssemblyLoad/FindInLoadContext 使用。 But I think that no longer.但我认为不再如此。 At least for my case of a Windows Forms app booting up, the assembly load context from the top-level app is being used to look up Nuget packages far down the calling chain.至少对于我的 Windows 窗体应用程序启动的情况,来自顶级应用程序的程序集加载上下文被用于在调用链的下游查找 Nuget 包。

It's worth repeating that my little test console apps always found the Nuget package without adding the package as a dependency to the top-level console program.值得重申的是,我的小测试控制台应用程序总是找到 Nuget 包,而没有将该包作为依赖项添加到顶级控制台程序。 I wrote console programs to test the calling chain from the bottom up: Test1) console calls Nuget directly - found;我写了控制台程序,从下往上测试调用链:Test1)控制台直接调用Nuget——找到; Test2) console (w/o Nuget dependency) calls Assembly3 - Nuget found; Test2) 控制台(没有 Nuget 依赖项)调用 Assembly3 - 找到 Nuget; (Test3) console (w/o Nuget dependency) calls Assembly2 - Nuget found. (Test3)控制台(没有 Nuget 依赖项)调用 Assembly2 - 找到 Nuget。

Then I wrote a skeleton WindowsFormsTestApp to call Assembly2 (just like the console program did) - Nuget NOT found.然后我写了一个框架 WindowsFormsTestApp 来调用 Assembly2(就像控制台程序一样) - Nuget NOT found。 When I added a Nuget dependency to the WindowsFormsTestApp - Nuget was found by Assembly3.当我向 WindowsFormsTestApp 添加 Nuget 依赖项时,Assembly3 找到了 Nuget。

The final step was to add a Nuget package dependency to the WinFormsApp that started this whole mess.最后一步是向 WinFormsApp 添加一个 Nuget 包依赖项,从而引发了整个混乱。 Presto!快! Assembly3 found the Nuget package immediately. Assembly3 立即找到了 Nuget 包。

My (unproven) belief is that somewhere along the line of upgrades from NET 5 - NET 6 (several SDK versions of each one), the assembly load context rules changed somehow.我的(未经证实的)信念是,在从 NET 5 到 NET 6(每个版本的多个 SDK 版本)的升级过程中,程序集加载上下文规则以某种方式发生了变化。 I could be wrong, but I lean toward this belief because my code from App->Assembly2->Assembly3->Nuget did not change during several months of successful operation.我可能是错的,但我倾向于这种信念,因为我在 App->Assembly2->Assembly3->Nuget 中的代码在成功运行的几个月中没有改变。 And just a couple of weeks ago after another NET 6 SDK upgrade, things broke.就在几周前,在另一个 NET 6 SDK 升级之后,事情就发生了。

Hopefully, this record might help someone someday.希望这一记录有一天能对某人有所帮助。 It seems completely unintuitive to me to add a Nuget package dependency to the top-level Forms app to help Assembly3 find a Nuget package sitting in the same folder as all the other assemblies.将 Nuget 包依赖项添加到顶级 Forms 应用程序以帮助 Assembly3 找到与所有其他程序集位于同一文件夹中的 Nuget 包对我来说似乎完全不直观。

After all this, I am coming around to the idea that the top-level app must/should include dependencies on anything the app ever calls, including packages used by dependent assemblies.毕竟,我开始考虑顶级应用程序必须/应该包含对应用程序调用的任何内容的依赖项,包括依赖程序集使用的包。 (Although I am still puzzled as to why the code worked for months before without the Nuget package dependency.) (尽管我仍然对为什么代码在没有Nuget 包依赖项的情况下工作了几个月感到困惑。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 .NET 标准 + .NET 框架:无法加载文件或程序集“Ninject” - .NET Standard + .NET Framework: could not load file or assembly 'Ninject' NuGet package 因“无法加载文件或程序集”而中断 - NuGet package breaks with "Could not load file or assembly" '无法加载文件或程序集。 系统找不到指定的文件' - 打包后抛出 .NET 框架 NuGet package - 'Could not load file or assembly. The system cannot find the file specified' - thrown after packaging .NET Framework NuGet package 无法加载文件或程序集'System.Net.Http,Version = 4.1.0.0 .net framework 4.6 .net standard 1.3 - Could not load file or assembly 'System.Net.Http, Version=4.1.0.0 .net framework 4.6 .net standard 1.3 Nuget包引用导致“无法加载文件或程序集”? - Nuget package references cause “Could not load file or assembly” ? Elmah MySql Nuget包问题'无法加载文件或程序集' - Elmah MySql Nuget Package Issue 'Could not load file or assembly' 从 .NET Framework Web 应用程序使用 .NET Standard 失败并显示“无法加载文件或程序集...” - Using .NET Standard from .NET Framework web application fails with "Could not load file or assembly..." 无法加载文件或程序集当Net Framework引用Net标准库时 - Could not load file or assembly When Net Framework reference a Net Standard Library 无法加载文件或程序集'System.Net.Http,Version = 4.1.1.1 .Net Standard - Could not load file or assembly 'System.Net.Http, Version=4.1.1.1 .Net Standard 无法在引用 .Net 标准库的已发布 .Net 4.6.1 项目中加载文件或程序集“System.ComponentModel.Annotations” - Could not load file or assembly 'System.ComponentModel.Annotations' in published .Net 4.6.1 project referencing .Net Standard library
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM