【问题标题】:Additional probing paths for .NET Core 3 migration.NET Core 3 迁移的其他探测路径
【发布时间】:2019-07-02 01:30:46
【问题描述】:

问题的简短版本:

.NET Core 3 中是否有任何方法可以指定本地探测路径,使用与 app.config 中的 <probing> 元素相同的规则? 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 分组中。模板代码为:

{
  "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 文件。我还尝试了一些关于如何指定目录的变体。如果指定的程序集不在根程序目录中,程序总是会生成一个错误,指出找不到指定的程序集。该错误表示它正在寻找从App.deps.json 文件中获取的lib/netstandard2.0/HtmlAgilityPack.dll(或其他类似库)。

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

【问题讨论】:

    标签: c# .net .net-core migration


    【解决方案1】:

    因此,根据从this Github issue 获得的信息,我发现.NET Core 中没有与app.exe.config 中的&lt;probing&gt; 元素等效的当前元素。因此,没有简单的“将所有这些 .dll 放入子目录并从那里工作”的解决方案。

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

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

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

    此外,复制为后期构建生成的命令,并在 .csproj 文件 (&lt;Target Name="PostPublish" AfterTargets="Publish"&gt;) 中创建另一个目标元素,使用 $(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>
    

    【讨论】:

    • 你能确认它适用于 .net 5 和 wpf 吗?我为我的一个 dll 做了这个,但没有用!
    猜你喜欢
    • 2017-07-03
    • 2020-08-03
    • 2019-12-09
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 2018-04-15
    • 1970-01-01
    相关资源
    最近更新 更多