在构建后事件上更新本地 nuget 包

Posted

技术标签:

【中文标题】在构建后事件上更新本地 nuget 包【英文标题】:Updating local nuget package on post-build event 【发布时间】:2011-07-02 19:50:39 【问题描述】:

我的本​​地 nuget 库存储库分别用于我的个人和工作相关类库。

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

我发现所有工作都是通过带有 Visual Studio 命令提示符的 nuget 命令行完成的。所以我可以轻松地完成我需要的工作(当然我会完全了解命令而我不会!)

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

关于项目构建:

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

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

所以我的要求是以上。有其他人做到这一点吗?

【问题讨论】:

【参考方案1】:

所选解决方案看起来可行,但似乎有更简单的解决方案可以满足您的要求。

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

C:\<Path to project>\nuget spec

这会在规范文件中创建“令牌”,当您创建 nuget 包时,它将被项目的元数据替换。这包括文件版本。你会想要替换,因为从技术上讲,所有项目都应该拥有它们。

更多细节可以在这里找到:http://docs.nuget.org/docs/creating-packages/Creating-and-Publishing-a-Package#From_a_project

那么……

对于 .Net Framework(老式)项目,您可以在项目的 Post build 事件中执行以下操作:

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

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

对于 .Net Core 和标准项目,nuget 无法打包它们(请参阅 https://github.com/NuGet/Home/issues/4491)。相反,将此作为您的后期构建步骤:

dotnet pack "$(ProjectPath)" --no-build --include-source --include-symbols --output "&lt;path where you are hosting your local nuget repo&gt;"

当然,您可以调整选项以满足您的需求。有关dotnet pack 命令选项,请参阅https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-pack?tabs=netcore2x。

【讨论】:

如果要设置输出目录,也可以避免两步过程。此外,您可能需要考虑是否需要包含依赖项: nuget pack "$(ProjectPath)" -outputdirectory "c:\NuGetPackages" -IncludeReferencedProjects 这不适用于未将包路径公开为共享的远程 NuGet 提要。【参考方案2】:

以防万一其他人(比如我)遇到这个古老的问题 - 在当前时代(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>

【讨论】:

必须将我的目标修改为 好像*.nupkg 文件的目录发生了变化(VS 2019, 16.4.5)不再在$(OutputPath)下。 Mike Casas 提供了必要的解决方案(谢谢!!) 即使使用@hardyVeles 发现的$(Package) 变量:nuget add bin\$(Configuration)\$(PackageId).$(PackageVersion).nupkg -source c:\packages,您也可以在构建后部署到本地 Nuget 提要。 (确保选择“当构建更新项目输出时”)。 我跟随 okieh 和 Mike 并使用了以下内容(包括配置): 。我尝试使用 Nick's 但不断收到 nuget 9009 错误。在玩了一会儿之后,切换到项目修复并且它工作了(因为我在调试中使用配置)。 VS 2019 社区,16.8.6【参考方案3】:

Jeremy Skinner 写了a blog post,介绍了他如何执行包的自动构建并将它们上传到 NuGet 库。我认为它符合您的要求。

基本上,他使用 MsBuild 将版本(使用 MsBuild Community ExtensionsUpdateXml 任务)应用到 nuspec 文件并调用 nuget.exe 将其打包。

【讨论】:

【参考方案4】:

我最近为此发布了一个解决方案,它实际上在构建期间创建/更新了 nuspec 文件,因此不必手动执行此操作,然后创建 nupkg 文件。

您只需要添加一个用于将包复制到其目的地的构建后事件(或将其作为可选阶段添加到我的解决方案中)。

您可以找到带有walk-through guide here 和source code + binary here 的文章。

【讨论】:

【参考方案5】:

使用使用“PackageReference”标签的最新 nuget 包格式,您可以在 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>

【讨论】:

【参考方案6】:

我通过命令行解决了这个问题 假设您已将 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

它不是单行的,但你可以将它放在一个 bat 文件中,然后在你的后期构建中调用它。

【讨论】:

以上是关于在构建后事件上更新本地 nuget 包的主要内容,如果未能解决你的问题,请参考以下文章

nuget服务器搭建,以及如何发布一个Nuget包

Docker在Linux上运行NetCore系列使用私有Nuget与多个本地包引用运行ASPNetCore

本地工作中的 nuget 包

如何仅为调试构建运行 Visual Studio 构建后事件

Docker在Linux上运行NetCore系列使用私有Nuget与多个本地包引用运行ASPNetCore

如何使用本地构建的 nuget 包进行调试?