How to install a NuGet package based on major version - msbuild

We use myget.org as NuGet server and here I upload a package named e.g. mypackage with two different major versions e.g. 6.0.1 and 7.0.1, and there can be several versions for each major version but I always want to have the latest version though the correct specified major version. So in one branch of my code I want to have 6.0.X (X = latest) and from another branch I want to have 7.0.X
Currently I do below in my msbuild, where MyPackage id have major version in the name, but that is not scalable.
<ItemGroup>
<Packages Include="MyPackageX">
<Source>https://xxx.myget.org/myfeed/index.json</Source>
</Packages>
</ItemGroup>
<Exec Command="$(NugetExe) install %(Packages.Identity) -Source %(Source)
-OutputDirectory $(PackagesFolder)\Package -ExcludeVersion -noninteractive
-prerelease -verbosity detail" />
I would perfer to do it from a msbuild script. Is it possible?
Simplified example
Build.msbuild file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="4.6.3" />
</ItemGroup>
<Target Name="Build" />
</Project>
In the same folder I have a nuget.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositorypath" value="packages" />
</config>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
From my developer command I type: msbuild build.msbuild
But no NuGet is installed so it doesn't make much sense to use wildcard before this simple scenario works.

Related

JetBrains rider does not execute nuget packages with .targets files

We are testdriving JetBrains as IDE on top of standard dotnet sdk from Microsoft. No Visual Studio installed.
We have a nuget package, that implements an additional build step. It works in VS Express, and on the msbuild commandline, when VS Express is installed, but not in Rider without any VS installed.
What are we missing?
This is the nuget package:
\Package.nuspec
\build\nugetPostbuild.targets
\script\createPackageAndUpload.cmd
The targets file is as such:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="postbuildPackNuGetTarget" AfterTargets="Build">
<Message Importance="high" Text="Message from MyNuGetCustomTarget. Configuration: $(MSBuildThisFileDirectory)..\nuget_postbuild_script\createPackageAndUpload.cmd $(ProjectDir) $(ProjectFileName) $(ConfigurationName) $(TargetDir)" />
<Exec Command="$(MSBuildThisFileDirectory)..\nuget_postbuild_script\createPackageAndUpload.cmd $(ProjectDir) $(ProjectFileName) $(ConfigurationName) $(TargetDir)" />
</Target>
</Project>
The spec is as such:
<?xml version="1.0"?>
<package >
<metadata>
<id>nugetPostbuild</id>
<version>1.0.3</version>
<authors>thewindowsuser</authors>
<owners>thewindowsuser</owners>
<projectUrl>http://...</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>bla ...</description>
<releaseNotes>http://...</releaseNotes>
<copyright>Copyright ...</copyright>
<tags>some tags here</tags>
</metadata>
<files>
<file src="script\**" target="nuget_postbuild_script" />
<file src="build\**" target="build" />
</files>
</package>
this stuff hasn't been implemented yet. You can track status in our issue tracker: RIDER-2149

MSBuild cannot find a reference - ReactJs.NET

After upgrading Newtonsoft.Json to version 9.0.0 and ReactJS.Net packages to 2.5.0, the TransformBabel.proj stopped working:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="TransformBabel">
<!-- ReactJS.NET - Transpile JavaScript via Babel -->
<UsingTask AssemblyFile="$(OutputPath)\React.MSBuild.dll" TaskName="TransformBabel" />
<Target Name="TransformBabel">
<TransformBabel SourceDir="$(MSBuildProjectDirectory)" />
</Target>
</Project>
Returning the following:
TransformBabel.proj(6, 3): error MSB4018: The "TransformBabel" task failed unexpectedly.
[Exec] TransformBabel.proj(6, 3): error MSB4018: React.TinyIoC.TinyIoCResolutionException: Unable to resolve type: React.IReactSiteConfiguration ---> System.TypeInitializationException: The type initializer for 'React.ReactSiteConfiguration' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
It seems that it cannot load the Newtonsoft 6.0.0.0 version. The web.config has an assembly redirection:
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
But I am not sure that, as it is starting a new msbuild process, if it is being ignored. I would like to hint msbuild the location of the assembly, but no success until now.
A bit late to the party here, but hopefully my experience will help to anyone else having the same problem.
I have recently experienced the same issue with React.MSBuild 3.1.0. It seems that it has hardcoded a specific version as I have updated my Newtonsoft.Json to the latest (10.0.3) using NuGet and set redirection correctly, but the build kept failing on the same error as you have mentioned.
What I did is simply uninstall all the React packages (MSBuild and Core) and also Newtonsoft.Json (using -force as there were other dependencies) and then let NuGet install the React.MSBuild again. It has installed it with all dependencies what resulted in obtaining Newtonsoft.Json 9.0.1.
Not sure why do they restrict Newtonsoft.Json library to a specific version, but it is more a question to React developers. Unless you need a latest (or other specific version of it), this should fix the problem.
I know this is an old post...but here is my workaround:
I put Newtonsoft.Json.dll v6.0.0.0 into Tools directory relative to the project directory and let msbuild copy it to $(OutputPath) to satisfy TransformBabel task condition.
My TransformBabel.proj looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="TransformBabel">
<!-- ReactJS.NET - Transpile JavaScript via Babel -->
<UsingTask AssemblyFile="$(OutputPath)\React.MSBuild.dll" TaskName="TransformBabel" />
<Target Name="TransformBabel">
<Copy SourceFiles="$(MSBuildProjectDirectory)\Tools\Newtonsoft.Json.dll" DestinationFolder="$(OutputPath)" />
<TransformBabel SourceDir="$(MSBuildProjectDirectory)" />
</Target>
</Project>
After this TransformBabel task is finished, then let msbuild overwrite Newtonsoft.Json.dll v6.0.0.0 in $(OutputPath) with whatever Newtonsoft.Json.dll version my project is actually using, ex: v8.0.3.
So, in the main project .csproj, I have something like this:
<ItemGroup>
...
<Reference Include="React.MSBuild, Version=2.3.0.0, Culture=neutral, PublicKeyToken=9aed67b161f7db78, processorArchitecture=MSIL">
<HintPath>Tools\React.MSBuild.dll</HintPath>
<Private>True</Private>
</Reference>
...
</ItemGroup>
...
<ItemGroup>
...
<Content Include="Tools\Newtonsoft.Json.dll" />
<Content Include="Tools\React.MSBuild.dll" />
...
</ItemGroup>
...
<Target Name="TransformBabel" AfterTargets="Build">
<Exec Command=""$(msbuildtoolspath)\msbuild.exe" $(ProjectDirectory)TransformBabel.proj /p:OutputPath=$(OutputPath) /nr:false" />
</Target>
<Target Name="AfterTransformBabel" AfterTargets="TransformBabel">
<Copy SourceFiles="..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll" DestinationFolder="$(OutputPath)" />
</Target>
Replace the path Newtonsoft.Json.8.0.3 inside AfterTransformBabel task to your need.

How can I use MSBuild 'afterbuild' tasks to edit a .config file?

I have a .config in a target project and I need to add a line to it programmatically via an MSBuild task.
Pseduo operations like:
find target .config file
determine the value of attributes for new node (e.g. 'id' and 'version' for 'package' node)
insert new node in correct parent node
save changes
The .config file at $TargetProjectDir\Config\packages.config:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ABC" version="1.1.0.4" />
<package id="XYZ" version="2.0.0.0" />
</packages>
Needs to look like this afterwards:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ABC" version="1.1.0.4" />
<package id="XYZ" version="2.0.0.0" />
<package id="CarDataWidget" version="3.0.0.0" />
</packages>
So far i've considered using 'inline tasks', the 'EXEC' task and 'XmlPoke' task but haven't managed to get any of them working.
Here is my attempt with XmlPoke and XmlPeek:
I used the following article as an inspiration on how to add nodes to the packages.config file:
http://weblogs.asp.net/bsimser/appending-nodes-in-xml-files-with-xmlpeek-and-xmlpoke-using-nant
<Target Name="AfterBuild" DependsOnTargets="AddPackage">
</Target>
<Target Name="AddPackage">
<!-- Load existing nodes into a Property -->
<XmlPeek XmlInputPath="config/packages.config" Query="/packages/package" >
<Output TaskParameter="Result" PropertyName="Peeked" />
</XmlPeek>
<Message Text="From Peek: $(Peeked)"></Message>
<!-- Load new node into Property -->
<PropertyGroup>
<WidgetName>CarDataWidget</WidgetName>
<WidgetVersion>2.0.0.0</WidgetVersion>
<NewNode><package id="$(WidgetName)" version="$(WidgetVersion)" /></NewNode>
<!-- Concatenate existing and new node into a Property -->
<ConcatenatedNodes>$(Peeked)$(NewNode)</ConcatenatedNodes>
</PropertyGroup>
<Message Text="New pacakges: $(ConcatenatedNodes)"></Message>
<!-- Replace existing nodes with concatenated nodes -->
<XmlPoke Value="$(ConcatenatedNodes)" XmlInputPath="config/packages.config" Query="/packages">
</XmlPoke>
</Target>
The output from the above build is:
1>AddPackage:
1> From Peek: <package id="ABC" version="1.1.0.4" />;<package id="XYZ" version="2.0.0.0" />
1> New pacakges: <package id="ABC" version="1.1.0.4" />;<package id="XYZ" version="2.0.0.0" /><package id="CarDataWidget" version="2.0.0.0" />
1> C:\_dev\CarDataWidget.csproj(184,14):
error MSB4094: "<package id="ABC" version="1.1.0.4" />;<package id="XYZ" version="2.0.0.0" /><package id="CarDataWidget" version="2.0.0.0" />"
is an invalid value for the "Value" parameter of the "XmlPoke" task.
Multiple items cannot be passed into a parameter of type "Microsoft.Build.Framework.ITaskItem".
1>
1>Build FAILED.
THE QUESTION:
How can get it to add to a .config file with existing package nodes???
I had the same problem. I found the solution here.
The problem is than XmlPoke considers semicolon as a value separator.
Should replace this:
<NewNode><package id="$(WidgetName)" version="$(WidgetVersion)" /></NewNode>
With:
<NewNode>&lt%3Bpackage id&#61%3B&quot%3B$(WidgetName)&quot%3B version&#61%3&quot%3$(WidgetVersion)&quot%3 /&gt%3</NewNode>
Must replace each semicolon by the secuence %3B
Here is a way to do it using MSBuild Extension Pack.
Set the packages and versions in the NewPackage item group and it adds them to the XML file.
<Project
ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks" />
<Target Name="Test" DependsOnTargets="AddPackage">
</Target>
<ItemGroup>
<NewPackage Include="CarDataWidget">
<Version>3.0.0.0</Version>
</NewPackage>
<NewPackage Include="FooBarWidget">
<Version>1.2.3.4</Version>
</NewPackage>
</ItemGroup>
<Target Name="AddPackage">
<PropertyGroup>
<InputFile>in.xml</InputFile>
<OutputFile>out.xml</OutputFile>
</PropertyGroup>
<Copy SourceFiles="$(InputFile)" DestinationFiles="$(OutputFile)" />
<MSBuild.ExtensionPack.Xml.XmlFile
TaskAction="AddElement"
File="$(OutputFile)"
XPath="//packages"
Element="package"
Key="id"
Value="%(NewPackage.Identity)" />
<MSBuild.ExtensionPack.Xml.XmlFile
TaskAction="AddAttribute"
File="$(OutputFile)"
XPath="//packages/package[#id='%(NewPackage.Identity)']"
Key="version"
Value="%(NewPackage.Version)" />
</Target>
</Project>
Not hoping to wake up an old thread.I had the exact scenario were I had to add new keys to the appsettings section of web.config. I started off with OPs code and was stuck with the same problem with ; in the peeked value preventing the new concatenated value to be written. I fixed it by using Replace function to remove the ;
<ConcatenatedNodes>$(Peeked)$(NewNode)</ConcatenatedNodes>
<!--in the concatenatednode, remove semicolon-->
<ChangedPeek>$(ConcatenatedNodes.Replace(";",""))</ChangedPeek>
<!-- Replace existing nodes with concatenated nodes-->
<XmlPoke XmlInputPath="%(WebConfigFilesSolutionDir.FullPath)" Query="//appSettings" Value="$(ChangedPeek)" />
For the complete answer on how to add a new key to appsetting section of webconfig using MSBuild refer https://stackoverflow.com/a/56760009/6664129
Take a look at my blog post http://sedodream.com/2011/12/29/UpdatingXMLFilesWithMSBuild.aspx which compares the following methods.
Use SlowCheetah to transform the files for you
Use the TransformXml task directly
Use the built in (MSBuild 4.0) XmlPoke task
Use a third party task library

how to run msbuild script through cruise control

I am getting execption when i am running cruise control by iis or cctray and below is ccnet.config.i wanted to run my scrip through cruise control .please let me know how to relove this issue
<project name="Visteon">
<webURL>http://localhost/ccnet/</webURL>
<triggers>
<intervalTrigger seconds="110" buildCondition="ForceBuild" />
</triggers>
<tasks>
<msbuild>
<executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
</executable>
<workingDirectory>E:\workingfolder_123</workingDirectory>
<buildArgs>E:\CCnet.xml /p:Configuration=release</buildArgs>
<timeout>1800</timeout>
<!-- 30 minutes -->
<logger>C:\Program Files\CruiseControl.NET\server\
ThoughtWorks.CruiseControl.MSBuild.dll</logger>
</msbuild>
</tasks>
</project>
</cruisecontrol>
my scripts is like this
<Target Name="GetSource">
<Message Text="Checking out trunk into $(SourceDirectory)" />
<SvnCheckout RepositoryPath="$(SvnCheckoutPath)"
LocalPath="$(CheckOutPath)"
UserName="aa"
Password="aa">
<Output TaskParameter="Revision" PropertyName="Revision" />
</SvnCheckout>
</Target>
<Target Name="Build" DependsOnTargets="GetSource;Clean;" />
<Target Name="Clean">
<!-- Clean, then rebuild entire solution -->
<MSBuild Projects="$(CheckOutPath)\SUPPLIER_SOFTWARE.sln" Targets="Clean;Rebuild" />
</Target>
Try using the CruiseControl Template below
<project name="MyCodeFolder Project" queue="MyQueue" queuePriority="1">
<tasks>
<msbuild>
<executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingDirectory>D:\Projects\MyCodeFolder</workingDirectory>
<projectFile>CCnet.xml</projectFile>
<buildArgs>/noconsolelogger /nologo /p:Configuration=Release</buildArgs>
<targets>
</targets>
<timeout>4800</timeout>
</msbuild>
</tasks>
As for the build script you will need the root to have Project node and set default target name main as the entry point. Please see below:
<Project DefaultTargets="Main">
<Target Name="Main">
//Do Something
</Target>
</Project>
You are missing project file tag e.g.
<projectFile>your_msbuild_script-here</projectFile>
http://build.sharpdevelop.net/ccnet/doc/CCNET/MsBuild%20Task.html
I'm also not sure what exactly E:\CCnet.xml is. If this is your msbuild file, put it
inside <projectFile/> and try again.
I hope that helps.

How to use shared ItemGroup element in batching tasks

I'm trying to automate the creation of Firefox addon for two different platforms by using MSbuild:
I have shared files set which are the same for Mac and Windows and have platform specific files.
I want to batch the task of making XPI(which is just a renamed Zip file) by platform, but I can't find the right way to add the platform agnostic(shared) files as input for Zip task. Currently, my solution is to duplicate shared files items with platform windows and with platform mac, and then batch Zip task by Platform parameter. I have a feeling that my solution is not optimal. Maybe community can propose a better solution. Below is the simplified solution I created with comments:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectMSBuildToolsPath Condition=" '$(ProjectMSBuildToolsPath)' == '' ">MSBuild</ProjectMSBuildToolsPath>
</PropertyGroup>
<!-- Required Import to use MSBuild Community Tasks -->
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<!-- Default platform type is shared-->
<ItemDefinitionGroup>
<ZipFiles>
<Platform>Shared</Platform>
</ZipFiles>
</ItemDefinitionGroup>
<ItemGroup>
<ZipFiles Include="chrome\overlay.js" />
<ZipFiles Include="chrome\Win\methodContainer.js">
<Platform>Win</Platform>
</ZipFiles>
<ZipFiles Include="chrome\Mac\dataContainer.js">
<Platform>Mac</Platform>
</ZipFiles>
</ItemGroup>
<Target Name="_PrepareItemsForZip" Outputs="$(Platform)">
<ItemGroup>
<!-- Merge Shared and Windows specific files -->
<ZipFilesToWin Include="#(ZipFiles)" Condition="('%(ZipFiles.Platform)' == 'Shared') Or ('%(ZipFiles.Platform)' == 'Win')" >
<Platform>Win</Platform>
</ZipFilesToWin>
<!-- Merge Shared and Mac specific files -->
<ZipFilesToMac Include="#(ZipFiles)" Condition="('%(ZipFiles.Platform)' == 'Shared') Or ('%(ZipFiles.Platform)' == 'Mac')" >
<Platform>Mac</Platform>
</ZipFilesToMac>
</ItemGroup>
<!-- Merge Mac and Windows files set -->
<ItemGroup>
<_ZipFiles Include="#(ZipFilesToWin);#(ZipFilesToMac)" />
</ItemGroup>
</Target>
<!-- batch zipping files based on input platform -->
<Target Name="MakeXPI" DependsOnTargets="_PrepareItemsForZip" Inputs="#(_ZipFiles)" Outputs="%(Platform)" >
<Message Text="Zipped files: #(_ZipFiles) %(Platform)" Importance="high"/>
<Zip Files="#(_ZipFiles)" WorkingDirectory="" ZipFileName="CoolAddon-%(Platform).xpi" ZipLevel="9" />
</Target>
</Project>
Extract them to file like SharedProperties.properties:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ZipFiles>
<Platform>Shared</Platform>
</ZipFiles>
<PropertyGroup>
</Project>
And then simply import in targets/script you need them:
<Project ... >
<Import Project="SharedProperties.properties" />