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

时间:2011-02-23 14:55:32

标签: c# asp.net visual-studio nuget post-build-event

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

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

我认为所有的工作都是由带有Visual Studio命令提示符的nuget命令行完成的。所以我可以很容易地完成我需要的工作(当然我会完全了解命令,但我不知道!)

基本上我希望在项目的post-build事件上执行以下任务。

关于项目构建:

  1. 将项目dll复制到特定文件夹(nuget包的lib文件夹)
  2. 更新新文件版本的nuspec文件(我的项目正在增加每个版本的文件版本)
  3. 使用新文件版本
  4. 创建新的nupkg文件 Phil Haack展示了这个功能,但据我所知,它仍然是原型。

    所以我的要求是以上。还有其他人做过这件事吗?

6 个答案:

答案 0 :(得分:11)

选择的解决方案看起来会起作用,但似乎有一个更简单的解决方案可以满足您的需求。

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

C:\<Path to project>\nuget spec

这会在spec文件中创建'标记',在创建nuget包时,它将被项目的元数据替换。这包括文件版本。您将需要替换,因为所有项目在技术上都假设有它们。

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

则...

对于.Net Framework(老派)项目,在项目的Post构建事件中,您可以这样做:

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

(假设您的系统PATH上有nuget.exe)。

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

dotnet pack "$(ProjectPath)" --no-build --include-source --include-symbols --output "<path where you are hosting your local nuget repo>"

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

答案 1 :(得分:6)

Jeremy Skinner撰写了a blog post关于他如何执行自动包构建并将其上传到NuGet Gallery的文章。我认为它符合您的要求。

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

答案 2 :(得分:1)

以防万一其他人(例如我)遇到这个古老的问题-在当前时代(VS2017,SDK / NugetReference格式/.NET Core / .NET Standard /多目标项目),在其中创建NuGet包是项目属性中的一个选项-因此,只需解决本地资源库的问题:

如果您具有单个目标项目,要将您的.nupkg文件复制到本地NuGet存储库,请添加构建后事件(项目属性>构建事件>构建后事件命令行):< / p>

  

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>

答案 3 :(得分:0)

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

您必须添加的是用于将软件包复制到目标的构建后事件(或将其作为可选阶段添加到我的解决方案中)。

您可以找到包含walk-through guide heresource code + binary here

的文章

答案 4 :(得分:0)

使用使用“ 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>

答案 5 :(得分:0)

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

我在名为D:\ Build的文件夹中有我的NuGet.exe和证书,您可能需要更新此文件以适合您的路径。

然后,让我们假设您有一个代码签名证书文件,名称为:“ 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文件中,并在您的帖子构建中调用它。