JetBrains rider does not execute nuget packages with .targets files - msbuild

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

Related

How to install a NuGet package based on major version

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.

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 get the Windows SDK folder in MSBuild?

What would be the way to retrieve the Windows SDK folder in an MSBuild task?
Using the generateBootstrapper task I'm creating a bootstrapper for my setup to be able to install the pre-requisites. This task needs the path to the folder where the pre-requisite packages are located, i.e. the Windows SDK folder
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\"
when using Visual Studio 2008. So far I have been using a hard-coded path but this won't work on any system. Is there a better way to get the path?
This is my build script:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="3.5">
<ItemGroup>
<BootstrapperFile Include="Microsoft.Net.Framework.2.0">
<ProductName>.NET Framework 2.0</ProductName>
</BootstrapperFile>
<BootstrapperFile Include="Microsoft.Windows.Installer.3.1">
<ProductName>Windows Installer 3.1</ProductName>
</BootstrapperFile>
</ItemGroup>
<Target Name="Bootstrapper">
<GenerateBootstrapper ApplicationFile="mySetup.msi"
Culture="de-DE"
ApplicationName="My Application"
OutputPath="$(OutDir)\de-DE"
BootstrapperItems="#(BootstrapperFile)"
Path="C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\" />
<GenerateBootstrapper ApplicationFile="mySetup.msi"
Culture="en-US"
ApplicationName="My Application"
OutputPath="$(OutDir)\en-US"
BootstrapperItems="#(BootstrapperFile)"
Path="C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\" />
</Target>
</Project>
You can also use the GetFrameworkSdkPath MSBuild task.
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath" />
</GetFrameworkSdkPath>
For example:
<GenerateBootstrapper
ApplicationFile="$(SolutionName).application"
ApplicationName="$(ClickOnceAppTitle)"
ApplicationUrl="$(ClickOnceUrl)"
BootstrapperItems="#(BootstrapperFile)"
Culture="en"
FallbackCulture="en-US"
Path="$(WindowsSDKPath)"
OutputPath="." />
thanks John. According to your post I edited the MSBuild script to read the folder from the registry. It was however not necessary to append "Packages" on the end, that was another mistake in my original script.
The following is the working script:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WindowsSDKPath>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\GenericBootstrapper\3.5#Path)</WindowsSDKPath>
</PropertyGroup>
<ItemGroup>
<BootstrapperFile Include="Microsoft.Net.Framework.2.0">
<ProductName>.NET Framework 2.0</ProductName>
</BootstrapperFile>
<BootstrapperFile Include="Microsoft.Windows.Installer.3.1">
<ProductName>Windows Installer 3.1</ProductName>
</BootstrapperFile>
</ItemGroup>
<Target Name="Bootstrapper">
<GenerateBootstrapper ApplicationFile="mySetup.msi"
Culture="de-DE"
ApplicationName="My Application"
OutputPath="$(OutDir)\de-DE"
BootstrapperItems="#(BootstrapperFile)"
Path="$(WindowsSDKPath)" />
<GenerateBootstrapper ApplicationFile="mySetup.msi"
Culture="en-US"
ApplicationName="My Application"
OutputPath="$(OutDir)\en-US"
BootstrapperItems="#(BootstrapperFile)"
Path="$(WindowsSDKPath)" />
</Target>
</Project>
The install path of the Windows SDK is stored in the CurrentInstallFolder value of the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows
I followed the answer from Jeremy D, but that gave the error message:
error MSB3147: Could not find required file 'setup.bin' in 'C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\Engine'.
The reason is that the path to the bootstrapper (at least with V8.0A of the SDK) is a subdirectory under the path returned by the GetFrameworkSdKPath.
So the MSBuild code that works for me is:
<Target Name="AfterBuild">
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="WindowsSdkPath"/>
</GetFrameworkSdkPath>
<GenerateBootstrapper
ApplicationFile="myapp.msi"
ApplicationName="MyApplication"
BootstrapperItems="#(BootstrapperFile)"
OutputPath="$(OutputPath)"
Path="$(WindowsSdkPath)\Bootstrapper" />
</Target>
Note the \Bootstrapper suffix to $(WindowsSdkPath)
The path to the bootstrapper is stored under the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\GenericBootstrapper\3.5
To find out the packages folder, open this, read the "Path" registry value, and append "Packages" on the end and that should give you the full path to the folder you want.
For example:
string bootStrapperPackagesFolder = "";
RegistryKey regKey = Registry.LocalMachine.OpenSubKey
(#"SOFTWARE\Microsoft\GenericBootstrapper\3.5");
if (regKey != null)
{
bootStrapperPackagesFolder = (string)regKey.GetValue("Path");
if (bootStrapperPackagesFolder != null)
{
bootStrapperPackagesFolder += #"Packages\";
Console.WriteLine(bootStrapperPackagesFolder);
}
}