Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run MSBuild pack target in Visual Studio 2017

My question is similar to this and this.

I want to package a .Net Framework library in Visual Studio 2017 RC. In VS 2015 with project.json build system, I was able to accomplish this by importing a custom targets file into the .xproj file. This custom targets file took care of creating the nuspec file if it didn't exist, then running nuget pack, copying the resulting packages to local feed location, etc.

Do I need to do something similar in 2017 (haven't made a serious effort yet) or can I somehow enable the pack target in my .csproj file?

The docs here only show to run the pack target from the command line.

EDIT: I'm trying the below custom target referencing a Nuget 4.0 exe from the nightly builds...

<Target Name="PackNugets"  AfterTargets="Build">    
  <PropertyGroup>
    <NugetV4Path>$([System.IO.Path]::GetFullPath('path to nuget.exe'))</NugetV4Path>
  </PropertyGroup>

  <Exec Command="&quot;$(NugetV4Path)\nuget.exe&quot; pack &quot;$(MSBuildProjectDirectory)\$(PackageId).csproj&quot; -Symbols -OutputDirectory bin -Properties Configuration=Release"/>
</Target>

But I get the following error

System.InvalidCastException: Unable to cast object of type 'System.String' to type 'NuGet.Frameworks.NuGetFramework'.
  at NuGet.ProjectManagement.NuGetProject.GetMetadata[T](String key)
  at NuGet.ProjectManagement.PackagesConfigNuGetProject..ctor(String folderPath, Dictionary`2 metadata)
  at CallSite.Target(Closure , CallSite , Type , Object , Dictionary`2 )
  at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
  at NuGet.CommandLine.ProjectFactory.AddDependencies(Dictionary`2 packagesAndDependencies)
  at NuGet.CommandLine.ProjectFactory.ProcessDependencies(PackageBuilder builder)
  at NuGet.CommandLine.ProjectFactory.CreateBuilder(String basePath, NuGetVersion version, String suffix, Boolean buildIfNeeded, PackageBuilder builder)
  at NuGet.Commands.PackCommandRunner.BuildFromProjectFile(String path)
  at NuGet.CommandLine.PackCommand.ExecuteCommand()
  at NuGet.CommandLine.Command.ExecuteCommandAsync()
  at NuGet.CommandLine.Command.Execute()
  at NuGet.CommandLine.Program.MainCore(String workingDirectory, String[] args)

Something to do with one of the properties in the csproj? Does NugetFramework refer to the TargetFramework?

I am targeting net452 in my csproj, in case that helps.

EDIT: That exception is indeed about nuget attempting to parse the TargetFramework, but it is not clear whether it is failing at my csproj or at a dependency...

like image 871
Ken G Avatar asked Jan 31 '17 19:01

Ken G


4 Answers

EDIT: The latest updates to VS2017 have added the Pack action to the project context menu, so the below action can be changed as follows:

  • AfterTargets=Pack
  • Remove the Exec element
  • If you are targeting multiple frameworks, you may have to insert a \$(Configuration) after the \bin in the NugetPackages Include.

Ok, this issue solved it for me. For now, we have to use dotnet instead of msbuild or nuget.

So, my custom target in the imported .targets file becomes

<Project ToolsVersion="15.0">
 <Target Name="PackNugets"  AfterTargets="AfterBuild">  

  <!-- Swap out nuget for dotnet and update the cli args -->
  <!-- Might actually be able to leave out the csproj path, since
       this target should run in the project directory. Test it first. -->
  <Exec Command="dotnet pack &quot;$(MSBuildProjectDirectory)\$(PackageId).csproj&quot; --no-build --include-symbols -o bin -c Release"/>

  <!-- If you want to copy to a local feed -->
  <ItemGroup>
    <NugetPackages Include="$(MSBuildProjectDirectory)\bin\$(PackageId).$(PackageVersion)*.nupkg"/>
   </ItemGroup>

  <Copy SourceFiles="@(NugetPackages)" DestinationFolder="path to local feed" />
 </Target>  
</Project>
like image 127
Ken G Avatar answered Oct 21 '22 19:10

Ken G


I was wanting to know the same thing, so I went spelunking in the MSBuild files, namely: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Sdks\NuGet.Build.Tasks.Pack\build and look for the "Pack" target.

Beyond that, I would refer to general MSBuild command line syntax here, but a few examples:

msbuild.exe -t:Pack -p:IncludeSymbols=true
msbuild.exe -t:Pack -p:Configuration=Release -p:VersionSuffix="alpha" # or "-alpha" - not sure

EDIT: A little more research and work on my scenario and I found this documentation of the important properties.

like image 40
Adam Hewitt Avatar answered Oct 21 '22 20:10

Adam Hewitt


Please note that dotnet pack or msbuild /t:Pack currently doesn't support .NET Framework projects. They only work NETCore projects.

like image 2
rohit21agrawal Avatar answered Oct 21 '22 20:10

rohit21agrawal


You can even improve Ken G answer if you want to push the nuget using this:

<Target Name="PushNugetPackage" AfterTargets="Pack" Condition="'$(Configuration)' == 'Release'">
  <Exec Command="nuget.exe push -Source &quot;mysource&quot; -ApiKey VSTS $(OutputPath)..\$(PackageId).$(PackageVersion).nupkg" />
</Target>

It will only run after you choose pack from context menu and configuration is Release, so you don't push debug packages, remove that condition if you really don't need it

Source

like image 1
David Noreña Avatar answered Oct 21 '22 21:10

David Noreña