c# - 如何创建一个 nuget 包,将文件复制到消费者的构建输出

标签 c# msbuild nuget

网上有大量关于创建 nuget 包的 Material ,但是,似乎也有大量的选项(dotnet pack、nuget.exe pack、msbuild t:pack 等)。我尝试了 official docs 中的几个建议,但我所能管理的就是将 *.dll 复制到使用项目的二进制输出文件夹中。我很挣扎,因为我在网上找到的大多数文档都没有提到文档是否谈论当前的 nuget 包输出文件夹或消费者。这种区别对我来说意义重大。

这就是我想要的

  • 我有三个文件:some.dll、some.tlb 和 some.txt。包含在 myNuGetPackage.nupkg 中
  • 当 msbuild 为消费 csproj 运行时,我希望将它们全部复制到消费解决方案/csproj 的二进制输出文件夹
  • 使用<PackageReference>在消费 csproj 中
  • 我不一定要构建 myNuGetPackage.csproj,因为我没有创建任何内容。我有这些文件并想将它们压缩。如果除了创建 myNuGetPackage.csproj 之外没有其他选择,我会这样做。
  • 我希望解决方案尽可能简单。我更愿意打开一个像“nuget package explorer”这样的工具,添加我的三个文件,但我认为这是不可能的?
  • 我认为这并不重要,但我想以 .NETFramework 4.8 为目标

这是我尝试过但失败的方法:

  • 我只尝试使用 nuget.exe pack my.nuspec 创建我自己的 my.nuspec
  • copyToOutput来自contentFiles see here

这是我的myPackage.nuspec的确切内容

<?xml version="1.0"?>
<package >
  <metadata>
    <id>myPackage</id>
    <version>1.0.0</version>
    <authors>me</authors>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>bla bla</description>
    <dependencies>
      <group targetFramework=".NETFramework4.8.0" />
    </dependencies>
        <contentFiles>
            <files include="**/*.tlb" buildAction="None" copyToOutput="true" flatten="true" />
            <files include="any/any/*.txt" buildAction="Compile" copyToOutput="true" flatten="true"/>
            <files include="any/any/*.xml" buildAction="EmbeddedResource" copyToOutput="true" flatten="true"/>
        </contentFiles>
  </metadata>
</package>

我的文件结构是

lib\net48\my.dll --> 被复制以构建消费者的输出

content\any\any\my.tlb content\any\any\my.xml content\any\any\my.txt --> 这些都不会被复制来构建消费者的输出。

我注意到我的所有文件都包含在 .nupkg 中,并且所有文件都被提取到 <users>\packages\myPackage\1.0.0\content\any\any不管我是否设置 copyToOutputtruefalse 。这告诉我,copyToOutput实际上应该将文件复制到使用的构建文件夹中。为什么它在我的情况下不起作用?

最佳答案

我会尽力将其分解。我创建了一个sample project如果您愿意,也可以跟随此处 ( https://github.com/BenjaminMichaelis/Samples/tree/main/CopyFilesInNugetPackage )。要生成 .nupkg,您只需运行 dotnet pack -o .在根目录中。

首先在您的 nuget 项目的 .csproj 中。第一行对于模式来说是特殊的,告诉它在构建时不执行任何操作。 PropertyGroup只是一些标准设置。

有趣的是,在 ItemGroup 中,我们首先声明 Include=它使用通配模式指向我们想要抓取的项目的相对路径。在我的示例存储库中,您会看到有一个 file3.json在 TestFiles/Folder1 中,这不会被拾取,因为它只在 TestFiles 中搜索。然而,TestFiles/Folder1 中的 file2.html 确实被拾取,因为 ** 全局模式事先告诉它递归搜索。相同的逻辑适用于 markdown 和 .targets 文件。您可以使用此逻辑将所需的任何文件包含到 nuget 包中。 .targets 文件对于自动复制到目标项目至关重要。您可以更改这些值以从 bin 内或任何地方获取您想要的文件。

然后是PackagePath=指向我们希望将其存储在包本身中的目录。

最终使用 dotnet pack -o . 打包项目后我可以使用https://github.com/NuGetPackageExplorer/NuGetPackageExplorer轻松检查 .nupkg文件以查看我的包裹内部并确保一切都像我预期的那样。 (如果您不想制作,我也将生成的 nupkg 包含在存储库中)。

InsideOfTheNUPKG

CopyFilesNuget.csproj:

<Project Sdk="Microsoft.Build.NoTargets/3.7.0">
  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <NoWarn>NU5128</NoWarn>
    <IsPackable>true</IsPackable>
    <VersionPrefix>1.1.0</VersionPrefix>
  </PropertyGroup>

  <ItemGroup>
    <None Include="TestFiles/*.json" Pack="true" PackagePath="TestFiles" />
    <None Include="TestFiles/**/*.html" Pack="true" PackagePath="TestFiles" />
    <None Include="Markdown/*.md" Pack="true" PackagePath="Markdown" />
    <None Include="Build/CopyFilesNuget.targets" Pack="true" PackagePath="build\CopyFilesNuget.targets"/>
  </ItemGroup>

</Project>

最后,要在 MyProjectName.targets 文件中复制生成的文件(.targets 扩展名对于 https://learn.microsoft.com/visualstudio/msbuild/customize-your-build?view=vs-2019&WT.mc_id=8B97120A00B57354#import-order 很重要),您可以执行以下操作:

CopyFilesNuget.targets:

<Project>
  <ItemGroup>
    <TestFilesFilesToCopy Include="$(MSBuildThisFileDirectory)../TestFiles/**/*.*"/>
    <MarkdownFilesToCopy Include="$(MSBuildThisFileDirectory)../Markdown/*.*"/>
  </ItemGroup>
  <Target Name="CopyContent" BeforeTargets="Build">
    <Copy SourceFiles="@(TestFilesFilesToCopy)" DestinationFolder="$(ProjectDir)TestFiles/%(RecursiveDir)" SkipUnchangedFiles="true" />
    <Copy SourceFiles="@(MarkdownFilesToCopy)" DestinationFolder="$(ProjectDir)Markdown/%(RecursiveDir)" SkipUnchangedFiles="true" />
  </Target>
</Project>

在这里,在第一个 ItemGroup 中,我们设置了要从 nuget 包中复制出来的目录的路径(我们在 csproj 中将它们设置为包中的目标),然后将其传递到复制任务中Target 作为 SourceFiles 变量。这些被复制到的位置是 DestinationFolder 值。

这里的一个重要部分是 <Target>使用标签。这会自动被使用项目使用,并且 BeforeTargets 告诉它在 msbuild 顺序中的哪个位置运行(在本例中是在 Build 之前)。

使用此 nupkg 文件,您可以在其他项目中使用它,但您通常会这样做(来自 nuget.org、本地、私有(private) nuget feed 等)

如果有任何问题请告诉我!

关于c# - 如何创建一个 nuget 包,将文件复制到消费者的构建输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77542596/

相关文章:

c# - 保留笔的大小?

c# - 如何: Nested Lists in SQLite-Net Extensions

c# - 'dotnet build' 指定主要方法

msbuild - 从 MSBuild 运行 grunt

c# - 使用 Mailkit 访问 Exchange 共享文件夹

c# - 分解集中式数据库的最具成本效益的方法是什么?

visual-studio-2010 - 如何使用命令行构建 SharePoint 2010 包?

tfs - 将内部 NuGet 服务器添加到 TFS 构建服务器?

asp.net - 创建自定义 nuget 包以在项目之间共享通用布局

nuget - 方法 'Given' 没有重载需要 4 个参数 - specflow