在后期构建事件中更新本地NuGet包

15

我为我的个人和工作相关的类库单独创建了本地NuGet库存储库。

我已经为一些不再开发的库创建了一些NuGet包。 我这样做只是因为我不知道如何在项目构建后自动更新它们。

我已经找到了所有工作都是由NuGet命令行和Visual Studio命令提示符完成的。 所以我可以很容易地做我需要的工作(当然我必须完全了解命令,但我不会!)

基本上,我希望在项目构建的后续事件中执行以下任务:

在项目构建时:

  1. 将项目dll复制到特定文件夹(NuGet包的lib文件夹中)
  2. 为新文件版本更新nuspec文件(我的项目在每次构建时都会增加文件版本)
  3. 使用新文件版本创建新的nupkg文件

Phil Haack展示了一些此功能,但据我所知,它仍然是一个原型。

所以我需要以上所述的要求。 有其他人完成了这个吗?

6个回答

17

所选方案看起来可以运行,但似乎存在更简单的解决方案适合您的需求。

您可以创建一个 nuspec 文件,该文件将从项目元数据中读取数据。只需使用此命令执行一次即可:

C:\<Path to project>\nuget spec

这将在规范文件中创建“令牌”,在创建NuGet包时将由项目元数据替换。这包括文件版本。您需要替换<version>和<authors>,因为所有项目技术上都应该有它们。

更多详细信息可以在此处找到:http://docs.nuget.org/docs/creating-packages/Creating-and-Publishing-a-Package#From_a_project

对于.Net Framework(老派)项目,在项目的后期构建事件中,您可以执行以下操作:

nuget pack "$(ProjectPath)"  
xcopy "$(TargetDir)*.nupkg" "<path where you are hosting your local nuget repo>" /C /Y

(假设nuget.exe在您的系统路径中可用)。

对于 .Net Core 和 Standard 项目,NuGet 无法对其进行打包(请参见https://github.com/NuGet/Home/issues/4491)。相反,将以下内容用作您的后置构建步骤:

dotnet pack "$(ProjectPath)" --no-build --include-source --include-symbols --output "<您托管本地NuGet存储库的路径>"

当然,您可以根据需要调整选项。有关dotnet pack命令选项,请参见https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-pack?tabs=netcore2x


6
如果您想设置输出目录,也可以避免进行两个步骤的过程。此外,您可能需要考虑是否需要包含依赖项:nuget pack "$(ProjectPath)" -outputdirectory "c:\NuGetPackages" -IncludeReferencedProjects - Kent Fehribach
这不适用于不将软件包路径公开为共享的远程 NuGet 源。 - Eric J.

7

如果您(和我一样)遇到这个古老的问题 - 在当前时代(VS2017,SDK / NugetReference格式/ .NET Core / .NET Standard / 多目标项目),创建NuGet程序包是项目属性中的一个选项 - 因此,只需解决本地存储库的问题:

如果您有单目标项目,请将.nupkg文件复制到本地NuGet存储库,添加后期生成事件(项目属性>生成事件>后期生成事件命令行):

xcopy $(TargetDir)*.nupkg [您的本地nuget存储库路径] /s

例如:

xcopy $(TargetDir)*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s


如果您有多目标项目,请将.nupkg文件复制到本地NuGet存储库: 添加后期生成事件(项目属性>生成事件>后期生成事件命令行):

xcopy $(TargetDir)..*.nupkg [您的本地nuget存储库路径] /s

例如:

xcopy $(TargetDir)..*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s


更新: 忘记后期生成事件,有一种更简洁的方法(xcopy方法对于多目标项目的工作方式很奇怪),只需在项目XML中添加以下内容:

  <Target Name="CopyPackage" AfterTargets="Pack">
    <Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
  </Target>

更新

对于较新的NuGet版本,会将版本号中的最后一个0(从0.0.0.0版本表示中)截掉,因此您需要使用正则表达式来查找PackageVersion:

  <Target Name="CopyPackage" AfterTargets="Pack">
    <Copy SourceFiles="$(OutputPath)$(PackageId).$([System.Text.RegularExpressions.Regex]::Replace(&quot;$(PackageVersion)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;)).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
  </Target>

3
我不得不修改我的目标为: <Target Name="CopyPackage" AfterTargets="Pack"> <Copy SourceFiles="$(ProjectDir)\bin\Release\$(PackageId).$(PackageVersion).nupkg" DestinationFolder="C:\Users\mcasas\Documents" /> </Target> (这是一个 XML 格式的代码段,它指定了一个名为“CopyPackage”的 MSBuild 目标,它将在“Pack”目标之后运行。该目标会将指定的文件复制到指定的文件夹中。) - Mike Casas
似乎 *.nupkg 文件的目录已更改(VS 2019,16.4.5)。它不再位于 $(OutputPath) 下。Mike Casas 提供了必要的解决方案(谢谢!!) - okieh
您可以使用@hardyVeles发现的$(Package)变量在构建后事件中部署到本地Nuget feed: nuget add bin\$(Configuration)\$(PackageId).$(PackageVersion).nupkg -source c:\packages。(确保选择“当构建更新项目输出”)。 - Nick Pearce
我跟随okieh和Mike的方法,使用以下代码(包括配置):<Target Name="CopyPackage" AfterTargets="Pack"> <Copy SourceFiles="$(ProjectDir)\bin\$(ConfigurationName)\$(PackageId).$(PackageVersion).nupkg" DestinationFolder="c:\repos\Daas.NuGet" /> </Target>。我尝试使用Nick的方法,但一直出现nuget 9009错误。经过一番尝试后,我切换到了项目修复方法,并且它成功了(由于我在Debug模式下进行了配置)。使用的是VS 2019 Community, 16.8.6版本。 - AlanC

4

Jeremy Skinner撰写了一篇关于如何执行自动化构建程序包并将其上传到NuGet Gallery的博客文章。我认为它符合您的要求。

基本上,他使用MsBuild将版本(使用MsBuild社区扩展 UpdateXml任务)应用于nuspec文件,并调用nuget.exe将其打包。


0

我最近发布了一个解决方案,可以在构建期间创建/更新nuspec文件,因此无需手动执行此操作,然后创建nupkg文件。

你只需要添加一个post-build事件来将包复制到它们的目标位置(或将其作为我的解决方案的可选阶段添加)。

你可以在这里找到一个 详细指南 ,以及 源代码和二进制文件


0

我通过使用命令行解决了这个问题。假设您已将NuGet的位置添加到路径环境中或将稳定版本复制到给定目录中(这就是我所做的)。

我将我的NuGet.exe以及证书放在名为D:\ Build的文件夹中,您可能需要更新此内容以适应您的路径。

然后假设您有一个名为“CodeSignCertificate.pfx”的代码签名证书文件,密码为:pa$$w0rd

您可以从Ascertia以17欧元获得简单的代码签名证书。他们还提供免费试用证书,有效期为10天。链接https://account.ascertia.com/onlineCA/default

然后作为一行代码,我使用:

for %f in (X:\Packages\*.nupkg) do D:\Build\nuget sign %f -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd

这个标记会在我的输出目录中为所有的软件包进行签名。

如果你只想签署最新的 NuGet 软件包,因为它可能是你刚编译的软件包,那么你可以使用类似下面的代码。

set Path="X:\ASP-WAF\DLL"
for /f "tokens=*" %%a in ('dir /A:-D /B /O:-D /S %Path%') do set NEW=%%a&& goto:n 
:n
sign %NEW% -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd

虽然不是一行代码,但你可以将它放入批处理文件中,在构建后调用该文件。


0

使用最新的NuGet包格式,使用“PackageReference”标记,您可以在csproj中使用以下简单的postbuild事件来更新nuspec文件以获取最新的依赖项。

  <Target Name="AfterBuild">
     <WriteLinesToFile File="dependencies.xml" Overwrite="true" Lines=""/>
     <WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="&lt;dependencies&gt;"/>
     <WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="&lt;dependency id=&quot;%(PackageReference.Identity)&quot; version=&quot;%(PackageReference.Version)&quot; /&gt;" />
     <WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="&lt;/dependencies &gt;"/>
     <Exec Command="powershell -NonInteractive -executionpolicy Unrestricted -command &quot;$xml = [xml] (Get-Content Project.nuspec); $xml.package.metadata.RemoveChild($xml.package.metadata.dependencies); $dependencies = [xml](Get-Content dependencies.xml); $xml.Package.Metadata.AppendChild($xml.ImportNode($dependencies.Dependencies, $true)); $xml.Save('Project.nuspec')&quot;"/>
     <Delete Files="dependencies.xml" />
  </Target>

前提条件是您在项目目录中有一个包含其余元数据的nuspec文件。以下是一个示例nuspec文件:

<?xml version="1.0"?>
<package>
   <metadata>
      <id>Package Id</id>
      <version>1.0.0</version>
      <authors>Author name</authors>
      <owners>Owner name</owners>
      <description>Description</description>
      <contentFiles>
         <files include="**/content.zip" buildAction="None" copyToOutput="true" flatten="false" />
      </contentFiles>
      <dependencies>
      </dependencies>
   </metadata>
   <files>
      <file src="bin\Release\Project.dll" target="lib\net462" />
      <file src="bin\Release\Project.pdb" target="lib\net462" />
      <file src="bin\Release\file.zip" target="Content" />
   </files>
</package>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接