TeamCity: How tell MSBuild to take into account publish profile parameters? - msbuild

I have TeamCity build configuration with MSBuild step, when i would like to compile my project with publish profile. My publish profile is located in MyProject\Properties\PublishProfiles\profile.pubxml.
My profile.pubxml:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<PrecompileBeforePublish>True</PrecompileBeforePublish>
<EnableUpdateable>True</EnableUpdateable>
<DebugSymbols>False</DebugSymbols>
<WDPMergeOption>MergeAllOutputsToASingleAssembly</WDPMergeOption>
<UseMerge>True</UseMerge>
<SingleAssemblyName>project</SingleAssemblyName>
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>C:\DevelopmentFolder</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
</PropertyGroup>
</Project>
My build step:
Runner type: MSBuild
Build file path: MyProject.csproj
MSBuild version: Microsoft Build Tools 2013
MSBuild ToolsVersion: 12
Run platform: x86
Now i would like to compile my project with account of parameters from my publish profile. I try to create all parameters as system parameters of build configuration (as in TeamCity says to use "Build Parameters" instead of "/property:" in an MSBuild step. What does that mean?), but i think MSBuild does not take into account parameters, because i can't see in bin directory project.dll file.

Add TeamCity property system.PublishProfile and the value should be your pubxml profile name ("profile" in your example). Then add a build step which runs MSBuild with the target "WebPublish" - it works for me.

Related

MSBuild ignores GatherAllFilesToPublish?

So, I created a publish profile for my web app. I did this with the GUI in VS 2017 Enterprise. I then found an example of how to change the pubxml to make it zip all the output files. Eventually I ended up with this:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<PublishProvider>FileSystem</PublishProvider>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<PrecompileBeforePublish>True</PrecompileBeforePublish>
<EnableUpdateable>True</EnableUpdateable>
<DebugSymbols>False</DebugSymbols>
<WDPMergeOption>DonotMerge</WDPMergeOption>
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>bin\Release\Publish</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
<Configuration>Release</Configuration>
</PropertyGroup>
<Target Name="ZipPublishOutput" AfterTargets="GatherAllFilesToPublish">
<Exec Command='powershell -nologo -noprofile -command "compress-archive -force -path $(WPPAllFilesInSingleFolder)\* -destinationpath $(publishUrl).zip"' />
</Target>
</Project>
This works perfectly fine if I do a publish through Visual Studio. However, I've been trying everything I can think of to get this to work in MSBuild, with no luck.
Here is an example of what I think should work:
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe" WebApp.csproj /nologo /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=ReleasePublish
And for reference, here is the version of MSBuild:
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Framework
I know MSBuild is finding the profile pubxml because I can make a change to the settings, such as publishUrl, and those changes are applied the next time I run MSBuild. What doesn't seem to work is the ZipPublishOutput target. And even running MSBuild with diagnostic verbosity shows that GatherAllFilesToPublish never runs, which would mean my target wouldn't run.
I've found many different suggestions and nothing seems to help. A lot of the solutions I found seemed to be with MSBuild not finding the pubxml, but that's not the case here.
So, is GatherAllFilesToPublish something that is Visual Studio specific, and therefore MSBuild doesn't know about it? That seems like how it's acting.
Just got the same problem using msbuild with Jenkins.
To execute the target GatherAllFilesToPublish with msbuild I had to add the target /t:GatherAllFilesToPublish in the msbuild command line.
You should have something like this :
/p:DeployOnBuild=true /p:PublishProfile=fullPathToMyPubXML.pubxml
/t:GatherAllFilesToPublish

Inexplicably cleared msbuild properties in TeamCity build

I'm trying to create a "tools NuGet package" that provides a tool and setting that is unpacked during build and used by a later TeamCity build step.
The NuGet package contains the following content in its build\MyPackageId.props file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MyTool1>$(MSBuildThisFileDirectory)..\tools\MyTool.exe</MyTool1>
</PropertyGroup>
<Target Name="ReportMyToolToTeamCity" BeforeTargets="PrepareToRun">
<PropertyGroup>
<MyTool2>$(MSBuildThisFileDirectory)..\tools\MyTool.exe</MyTool2>
</PropertyGroup>
<Message Text="MyTool1 = $(MyTool1)" />
<Message Text="MyTool2 = $(MyTool2)" />
</Target>
</Project>
(The messages will eventually set a TeamCity property, but this is sufficient to demonstrate the issue.)
Because it's a props file, after installing the NuGet package into a C# project it has added an import as the very first thing, above the import of Microsoft.Common.props. I want a props file rather than a targets file so that the property values are also available to other project settings and targets files.
When I compile this inside Visual Studio 2015, I see both MyTool1 and MyTool2 paths set to the same (correct) path as expected.
When I compile this from TeamCity (2017.2.2, using the Visual Studio (sln) runner), according to the output the MyTool1 property is empty and only MyTool2 shows the correct value.
Why?

VSTS msbuild: How to use parameters instead of profile? Error: Could not find __.dll

I have a simple "Hello World" mvc web application that I am attempting to build in VSTS. My steps are:
Get Sources
Run msbuild on a single project
Publish artifact (publish directory)
Everything works fine whenever I use a profile for msbuild, but I would like to just pass the parameter commands in instead. When I do this I get the following error:
Error : Copying file bin\WebApp01.dll to obj\Release\Package\PackageTmp\bin\WebApp01.dll failed. Could not find file 'bin\WebApp01.dll'.
What mistake am I making with my msbuild parameters? How do I properly duplicate a simple file system profile?
Parameters (error'ing):
/p:DeployOnBuild=true /p:Configuration="Release" /p:Platform="Any CPU" /t:WebPublish /p:WebPublishMethod=FileSystem /p:publishUrl=PublishToOctopus
Profile (works):
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>PublishToOctopus</publishUrl>
<DeleteExistingFiles>False</DeleteExistingFiles>
</PropertyGroup>
</Project>
When using /p:DeployOnBuild=true, you can use the normal Build target. You directly called WebPublish (/t:WebPublish) which expects a build to already have happened but since it doesn't, the file is missing from the expected location.

How to use MSBuild to build multiple platforms

I am using Visual Studio online build with an MSBuild task. I currently have the following MSBuild Arguments fed to my task:
/p:Configuration=Release;AppxBundle=Always;AppxBundlePlatforms="x86|x64|ARM";AppxPackageDir="$(Build.BinariesDirectory)\AppxPackages\\";UapAppxPackageBuildMode=StoreUpload
This creates my application in x86, x64 and ARM. It creates Release version of the libraries in x86 BUT creates Debug version of my libraries in x64 and ARM.
When my .appxupload package is creates it fails Windows Certification tests because my libraries are built in debug.
How can I make MSBuild build for all 3 configurations. My guess is because I haven't provided a /platform configuration. How do I provide this configuration for 3 platforms?
I have tried platform="x86|x64|ARM" but it returned an error
For a standard project file there's no way to do this in a single command. Either use multiple commands to build the project for each platform/configuration combination needed, or use a 'master' build file which does the same for you, something like:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="FullRebuild">
<Target>
<ItemGroup>
<Configurations Include="Debug;Release"/>
<Platforms Include="x86;x64;ARM"/>
<ConfigAndPlatform Include="#(Configurations)">
<Platform>%(Platforms.Identity)</Platform>
</ConfigAndPlatform>
</ItemGroup>
<MSBuild Projects="myproject.sln" Targets="Build"
Properties="Configuration=%(ConfigAndPlatform.Identity);Platform=%(ConfigAndPlatform.Platform)"/>
</Target>
</Project>

Referencing macros on msbuild (12.0) command line property assignment

I am curious, is it possible to reference a macro on a command line property assignment for MSBuild?
E.g:
msbuild.exe MySolution.sln /p:CustomBeforeMicrosoftCSharpTargets="$(SolutionDir)\custom.targets"
Would this also work when specified as "MSBuildArguments" from an "Edit Build Definition"/"Queue New Build" from Visual Studio connected to TFS?
E.g:
/p:CustomBeforeMicrosoftCSharpTargets="$(SolutionDir)\custom.targets"
Because it doesn't appear to be importing these targets for me. But the targets file is definitely there, alongside the solution, in the build workspace.
I don't want to have to specify an absolute path. Not sure how working with relative paths is meant to work here, can't find any advice on the internet, and debugging it is quite difficult, as it is called on a build agent using a workflow. The workflow logging is definitely reporting it is calling MSBuild with these arguments, but nowhere in the verbose logging output can I see it is making reference to the CustomBeforeMicrosoftCSharpTargets target, or calling it.
EDIT
I wrote a little test build project buildme.proj to further my understanding.
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SetMe>NotInTheSandbox</SetMe>
</PropertyGroup>
<PropertyGroup>
<SomeMacroValue>c:\Sandbox\BuildTest</SomeMacroValue>
</PropertyGroup>
<PropertyGroup>
<AlreadySet>$(SomeMacroValue)\InTheSandbox</AlreadySet>
</PropertyGroup>
<Target Name="Build">
<Message Text="I am building!" />
<Message Text="Some macro value: $(SomeMacroValue)" />
<Message Text="$(SetMe)" />
<Message Text="$(AlreadySet)" />
</Target>
</Project>
When I execute with the command:
msbuild buildme.proj /p:SetMe="$(SomeMacroValue)\StillNotInSandbox"
I get the following output:
Microsoft (R) Build Engine version 12.0.31101.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 10/12/2015 22:12:08.
Project "C:\Sandbox\BuildTest\buildme.proj" on node 1 (default targets).
Build:
I am building!
Some macro value: c:\Sandbox\BuildTest
$(SomeMacroValue)\StillNotInSandbox
c:\Sandbox\BuildTest\InTheSandbox
Done Building Project "C:\Sandbox\BuildTest\buildme.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.02
So clearly, it is not behaving how I expected: The macro identifier appears in the output message text.
Is there a solution to this?
A "macro" like $(SolutionDir) exists only in VisualStudio and VS passes the value to MSBuild.
Instead MSBuild makes Environment variables available as properties, so a batch file like this
set SomeMacroValue=foo
msbuild buildme.proj /p:SetMe="$(SomeMacroValue)\StillNotInSandbox"
is probably what you are looking for.
And you can set environment variables per-user or per-machine (Control Panel\All Control Panel Items\System Advanced System Settings, Environment variables).