为什么 NuGet 包中的内容文件作为链接添加到 .NET Core 项目中,您如何防止这种情况发生?

Why are content files from NuGet packages added as links in .NET Core projects and how can you prevent that?

我正在开发 .NET Standard 库并计划在 .NET Core 和 .NET Framework 项目中使用它。我的库依赖于第三个库,它本身依赖于一些 C 二进制文件。必须将 C 二进制文件复制到将引用我的库的项目的输出目录。

我将二进制文件作为内容添加到我的库项目中,当使用 dotnet pack 命令打包 NuGet 包时,它们被复制到 contentcontentFiles 目录。这些文件也列在 nuspec 文件中。


但是,当我安装 NuGet 包时,有两种不同的行为需要观察,具体取决于我将其安装到 .NET Framework 还是 .NET Core 项目:

.NET 框架

我添加到库项目的二进制文件也添加到引用项目,我可以将它们复制到输出目录。这是我期望、想要和有效的行为。

.NET 核心

我添加到我的库项目中的二进制文件也被添加到引用项目中但是作为链接也可以工作但是 在我的机器上 当然是因为 NuGet 包默认存储在 Windows 用户文件夹中。这会给将在不同机器上处理同一项目的任何其他人带来问题,因为在这种情况下文件链接会被破坏。


我已经试过弄乱 nuspec 文件本身,但这并没有真正帮助,因为我只在 CI 管道完成打包后才得到 nuspec 文件。

为什么 .NET Framework 和 .NET Core 项目的行为在那种情况下不同,是否可以在 .NET Core 项目中获得 .NET Framework 项目的行为?

其实这是正常现象。

而你所看到的内容和内容文件的行为是正常的,它们的规则是由微软设计的。

请参考this similar issue and this one

Content 节点会将其内容作为真实文件打包到主项目中。这适用于具有 packages.config nuget 管理格式的 Net Framework 项目。

ContentFiles 节点会将其内容打包为 link 格式到主项目中(Net Core网络标准 项目)。这是 PackageReference nuget 管理格式。

So 如果你想要这个功能与 Net Core[=74] 上的 Net Framework 项目相同=],你应该在 net standard 项目上使用 <package_id>.props 来获得你想要的。

步骤

1) 在您的网络标准库项目的 build 文件夹下创建一个名为 <packages_id>.props 的文件。

注意:如果您的 lib nuget 名为 lib.1.0.0.nupkg,props 文件应命名为 lib.props 文件,这样它才能正常工作。它应该与 nuget_id.

相同

2)lib.props 文件中添加这些:

<Project>
  <Target Name="CopyFiles" BeforeTargets="Build">
    <ItemGroup>     
      <File Include="$(MSBuildThisFileDirectory)..\Binary\*.*"></File>          
    </ItemGroup>
      <Copy SourceFiles="@(File)" DestinationFolder="$(ProjectDir)Binary"></Copy>
  </Target>
</Project>

3) 将这些添加到 lib 项目的 xxx.csproj 文件中。

<ItemGroup>
<None Include="xxx\**.**"(all the binary files) Pack="true" PackagePath="Binary"></None>
<None Include="build\lib.props" Pack="true" PackagePath="build"></None>
</ItemGroup>

4) 当您安装这个新版本的nuget 包。

另外,当您安装这个新版本的nuget包时,请clean your nuget caches或删除C:\Users\xxx(current user)\.nuget\packages下的所有文件。

除了,还有.

基于Perry Quian-MSFT's 我将二进制文件复制到输出目录而不是项目。

我认为这比用不必要的文件弄乱项目更好。

这是我的 props 文件的样子:

<Project ToolsVersion="4.0" xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
  <ItemGroup>
    <Binaries Include="$(MSBuildThisFileDirectory)..\binaries\*.*" />
  </ItemGroup>

  <Target Name="CopyBinaries" BeforeTargets="Build">
    <Copy SourceFiles="@(Binaries)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
  </Target>
</Project>

我想分享的成功 - 我正在使用 dotnetcore (.NET 6) 我需要分享一个 c# class 库以及常见的 json 配置文件并创建了一个包含内容文件和输出 nuget 包的库 class 项目。

利用其他好的答案 - 这是在结合其他建议后对我有用的答案。

在“lib”项目中 - 包含 build\lib.props 文件。内容:

<Project>
    <Target Name="CopyFiles" BeforeTargets="Build">
        <ItemGroup>
            <ConfigFilesShared Include="$(MSBuildThisFileDirectory)..\SharedConfig\*.*" />
        </ItemGroup>
        <Copy SourceFiles="@(ConfigFilesShared)" DestinationFolder="$(ProjectDir)SharedConfig" SkipUnchangedFiles="false"></Copy>
    </Target>
</Project>

以上在构建之前将文件复制到使用项目的文件夹中。

还在 lib.csproj 文件中包含以下内容:

<ItemGroup>
    <Content Include="Config\*" Pack="true" PackagePath="SharedConfig\" />
    <None Include="Build\Roc.Shared.props" Pack="true" PackagePath="build"></None>
</ItemGroup>

在“消耗”项目中 - 隐藏项目中的文件目录以免造成混淆我的 csproj 中有以下消耗共享图书馆:

<ItemGroup>
    <Content Remove="SharedConfig\**" />
    <None Remove="SharedConfig\**" />
</ItemGroup>

为确保文件同时包含在输出(常规构建)和发布中,使用了以下代码。

<!-- For Build - Move the shared library shared config files that were previously copied to the SharedConfig folder-->
<Target Name="PrebuildScriptShared" BeforeTargets="Build">
    <ItemGroup>
        <ConfigFiles1 Include="SharedConfig\**" />
    </ItemGroup>
    <Copy SourceFiles="@(ConfigFiles1)" DestinationFolder="$(OutDir)Config" SkipUnchangedFiles="false" />
</Target>
<!-- For Publish - Move the shared library shared config files that were previously copied to the SharedConfig folder-->
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
    <ItemGroup>
        <ConfigFiles2 Include="SharedConfig\**" />
    </ItemGroup>
    <Copy SourceFiles="@(ConfigFiles2)" DestinationFolder="$(PublishDir)Config" SkipUnchangedFiles="false" />
</Target>

还有!您现在拥有从 nuget 包复制到您的使用项目的内容文件,并在构建、调试和发布期间使用。 :)