c# - .NET Core 3 迁移的其他探测路径

标签 c# .net .net-core migration

问题的简短版本:

.NET Core 3 中是否有任何方法来指定本地探测路径,使用与 <probing> 相同的规则app.config 中的元素? additionalProbingPaths似乎不起作用。

问题的长版:

我正在将一个项目从 .NET Framework 迁移到 .NET Core 3。在原始项目中,我在 lib/文件夹中保留了许多辅助 dll。这很好用,因为我在 App.exe.config 中设置了探测路径,像这样:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="lib" />
    </assemblyBinding>
  </runtime>

但是,将项目转换为 .NET Core 3 后,程序将无法运行,说找不到 dll。 App.exe.config仍然存在,并且仍在被读取/使用,因为它还包含有关 System.Configuration 参数的信息,并且程序的那部分仍然可以正常工作。

我确定在 App.runtimeconfig.json 中有一个新的 json 文件存储程序的配置信息。 .它是自动生成的,默认情况下不包含额外的探测路径,但 App.runtimeconfig.dev.json文件包含一些。

现在,我无法使用 .dev.json 文件中的路径,因为这些路径指向本地用户目录,并且不能用于部署。但是,我可以通过使用项目目录中的模板文件 ( runtimeconfig.template.json ) 将我自己的版本添加到主 runtimeconfig 中。这会将属性添加到 runtimeOptions在主 runtimeconfig 文件中分组。模板代码为:
{
  "additionalProbingPaths": [
    "lib"   
  ]
}

以及 App.runtimeconfig.json 的最终输出文件是:
{
  "runtimeOptions": {
    "tfm": "netcoreapp3.0",
    "framework": {
      "name": "Microsoft.WindowsDesktop.App",
      "version": "3.0.0-preview6-27804-01"
    },
    "additionalProbingPaths": [
      "lib"
    ]
  }
}

然而,我插入的相对路径似乎根本没有被使用,无论是我使用模板将它插入到主 runtimeconfig 文件中,还是只是手动编辑 dev.json 文件。我还尝试了许多关于如何指定目录的变体。如果指定的程序集不在根程序目录中,程序总是会生成一个错误,指出未找到指定的程序集。错误说它正在寻找 lib/netstandard2.0/HtmlAgilityPack.dll (或其他类似的库)从 App.deps.json 获取文件。

解决方法是让所有库都存在于根程序目录中,但由于这以前可以工作,我希望它现在可以工作,我想知道我做错了什么。尝试使用 Visual Studio 中的诊断输出获取更多信息失败,因为程序在生成任何诊断信息之前终止。

最佳答案

因此,基于从 this Github issue 获得的信息,我发现没有电流相当于<probing>元素来自 app.exe.config在 .NET Core 中。因此,没有简单的“将所有这些 .dll 放入子目录并从那里工作”的解决方案。

但是,可以使用 additionalProbingPaths指令,如上所述,还有一些额外的调整。

首先设置additionalProbingPaths模板文件中的目录到“bin”之类的东西。这将定义新程序集存储位置的根,该位置将被构造为看起来像 NuGet 存储库。

然后在构建后事件中设置命令以移动(例如)HtmlAgilityPack.dll文件到 "$(TargetDir)bin/HtmlAgilityPack/1.11.8/lib/netstandard2.0" .完整路径由 deps.json 中提供的组装信息的两半构成。文件:"HtmlAgilityPack/1.11.8" , 和 "lib/netstandard2.0/HtmlAgilityPack.dll"位于 "runtime" 下小节。然后,正常的依赖项解析过程将能够根据 deps.json 中的内容找到它。文件,以及 bin探测路径。

此外,复制为后期构建生成的命令,并在 .csproj 文件 ( <Target Name="PostPublish" AfterTargets="Publish"> ) 中创建另一个 Target 元素,使用 $(PublishDir)而不是 $(TargetDir)定义输出。这将使构建系统在发布和构建时执行相同的文件移动。

这确实意味着每次更新包版本号时都要更新文件移动命令,因此需要额外的手动工作来保持它最新。

我希望他们能够改进构建系统以自动执行此类操作,因为除了清理内容之外,它还为多个版本的依赖项打开了选项,并且可能有助于解决 .NET 中持续存在的版本控制问题。

附录:一种将各种 DLL 移动到可用目录中的更简洁的方法。使用构建后代码窗口是一种可怕的处理方式,但使用标准 MSBuild 命令处理起来要容易得多。但是,当包版本更改时,它仍然需要手动更新。

下面为构建和发布进行设置。请注意,这些必须单独设置。在不同的“父”操作中定义目标目录变量后,您不能重构以使用一组移动命令,因为发布隐式首先构建,并且给定的目标操作只能被调用一次。所以一旦在构建过程中被调用,在发布过程中就不能再次调用。

<Target Name="CreateBuildBin" AfterTargets="Build">
    <MakeDir Directories="$(TargetDir)bin" Condition="!Exists('$(TargetDir)bin')" />
</Target>

<Target Name="MoveBuildDlls" AfterTargets="CreateBuildBin">
    <Message Importance="high" Text="Build directory = $(TargetDir)" />
    <Copy SourceFiles="$(SolutionDir)LICENSE.txt" DestinationFolder="$(TargetDir)" />
    <Move SourceFiles="$(TargetDir)HtmlAgilityPack.dll" DestinationFolder="$(TargetDir)bin/HtmlAgilityPack/1.11.17/lib/netstandard2.0" />
</Target>

<Target Name="CreatePublishBin" AfterTargets="Publish">
    <MakeDir Directories="$(PublishDir)bin" Condition="!Exists('$(PublishDir)bin')" />
</Target>

<Target Name="MovePublishDlls" AfterTargets="CreatePublishBin">
    <Message Importance="high" Text="Publish directory = $(PublishDir)" />
    <Copy SourceFiles="$(SolutionDir)LICENSE.txt" DestinationFolder="$(PublishDir)" />
    <Move SourceFiles="$(PublishDir)HtmlAgilityPack.dll" DestinationFolder="$(PublishDir)bin/HtmlAgilityPack/1.11.17/lib/netstandard2.0" />
</Target>

关于c# - .NET Core 3 迁移的其他探测路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56844233/

相关文章:

c# - 将 Task.WhenAll 与不断增长的任务列表一起使用

c# - 如何从文本文件中固定这个解析循环

c# - 无法加载文件或程序集 'log4net

c# - 为什么这个线程方法需要 900 毫秒才能完成?

c# - 如何在异常处理程序 - WebAPI 中获取请求 JSON 消息?

c# - 打破从 C# 开始的进程

c# - 在 ASP.NET Core 2 中初始化记录器服务之前记录异常的正确方法

templates - 在 dotnet 新模板中包含 "hidden"文件

c# - 加密 JWT 安全 token 支持的算法

c# - 在直接调用委托(delegate)的情况下如何缓解 "Access to modified closure"