TeamCity ignores AfterTargets - msbuild

I have a set up similar to the following:
Test.csproj: (default Windows console application, no changes)
Test.csproj.user:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="Test.csproj.targets" />
</Project>
Test.csproj.targets:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AfterCoreCompile" AfterTargets="CoreCompile">
<Message Text="In AfterCoreCompile" />
</Target>
</Project>
Using Visual Studio, the output looks like this:
------ Build started: Project: Test, Configuration: Debug x86 ------
Build started 8/24/2011 10:48:04 AM.
CoreCompile:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" /debug+ /debug:full /filealign:512 /optimize- /out:obj\x86\Debug\Test.exe /target:exe Program.cs Properties\AssemblyInfo.cs
AfterCoreCompile:
In AfterCoreCompile
CopyFilesToOutputDirectory:
Copying file from "obj\x86\Debug\Test.exe" to "bin\Debug\Test.exe".
Test -> C:\Users\...\Desktop\Test\Test\bin\Debug\Test.exe
Copying file from "obj\x86\Debug\Test.pdb" to "bin\Debug\Test.pdb".
Build succeeded.
Time Elapsed 00:00:00.09
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
In TeamCity it looks like this:
[10:50:05]: Skip checking for changes - there are no VCS roots defined
[10:50:05]: Clearing temporary directory: C:\TeamCity\buildAgent\temp\buildTmp
[10:50:05]: Checkout directory: C:\TeamCity\buildAgent\work\532794d203990edb
[10:50:05]: Repository sources transferred
[10:50:05]: Updating sources: server side checkout...
[10:50:05]: Publishing internal artifacts (4s)
[10:50:09]: [Publishing internal artifacts] Sending build.start.properties file
[10:50:05]: Starting: C:\TeamCity\buildAgent\plugins\dotnetPlugin\bin\JetBrains.BuildServer.MsBuildBootstrap.exe /workdir:C:\Users\buildbot\Desktop\Test /msbuildPath:C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe
[10:50:05]: in directory: C:\Users\buildbot\Desktop\Test
[10:50:06]: Targets was not defined in the build configuration.
[10:50:09]: Test.csproj.teamcity: Build target: Build
[10:50:09]: [Test.csproj.teamcity] CoreCompile
[10:50:09]: [CoreCompile] Csc
[10:50:09]: [Csc] C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorlib.dll /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework64\v2.0.50727\System.Xml.dll /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" /debug+ /debug:full /filealign:512 /optimize- /out:obj\x86\Debug\Test.exe /target:exe Program.cs Properties\AssemblyInfo.cs
[10:50:09]: [Csc] CSC warning CS1607: Assembly generation -- Referenced assembly 'mscorlib.dll' targets a different processor
[10:50:09]: [Csc] CSC warning CS1607: Assembly generation -- Referenced assembly 'System.Data.dll' targets a different processor
[10:50:09]: [Test.csproj.teamcity] CopyFilesToOutputDirectory
[10:50:09]: [CopyFilesToOutputDirectory] Copy
[10:50:09]: [Copy] Copying file from "obj\x86\Debug\Test.exe" to "bin\Debug\Test.exe".
[10:50:09]: [CopyFilesToOutputDirectory] Test.csproj -> C:\Users\Buildbot\Desktop\Test\bin\Debug\Test.exe
[10:50:09]: [CopyFilesToOutputDirectory] Copy
[10:50:09]: [Copy] Copying file from "obj\x86\Debug\Test.pdb" to "bin\Debug\Test.pdb".
[10:50:10]: Process exited with code 0
[10:50:10]: Publishing internal artifacts
[10:50:10]: [Publishing internal artifacts] Sending build.finish.properties file
[10:50:10]: Build finished
So why is TeamCity ignoring my AfterTargets targets?

The reason this happened was because the *.csproj.user files are ignored by TeamCity, despite their potential existence in the VCS. Moving the <Import Project="..." /> line into the *.csproj file resulted in the proper behavior.

Related

Incremental build in .NET Core & Visual Studio

This toy project doesn't have working incremental build:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<Timestamp>$([System.DateTime]::Now.ToString("yyyy-MM-dd\THHmmss"))</Timestamp>
</PropertyGroup>
<ItemGroup>
<MyInputs Include="myinput.txt" />
<MyOutput Include="myoutput.txt" />
</ItemGroup>
<Target
Name="test_BeforeTargets_BeforeBuild"
BeforeTargets="BeforeBuild"
Inputs="#(MyInputs)"
Outputs="#(MyOutput)"
>
<Message Text="test_BeforeTargets_BeforeBuild" Importance="high" />
<WriteLinestoFile File="myoutput.txt" Lines="$(Timestamp)" Overwrite="true" />
</Target>
</Project>
There are 3 build outcomes that I've noticed in Visual Studio:
When myinput.txt and the .csproj files are modified I get my desired outcome:
1>Target "test_BeforeTargets_BeforeBuild" in file "C:\Users\dan\source\repos\TestMSBuild\TestMSBuild.csproj":
1> Building target "test_BeforeTargets_BeforeBuild" completely.
1> Input file "myinput.txt" is newer than output file "myoutput.txt".
1> Task "Message"
1> Task Parameter:Text=test_BeforeTargets_BeforeBuild
1> Task Parameter:Importance=high
1> test_BeforeTargets_BeforeBuild
1> Done executing task "Message".
1> Task "WriteLinestoFile"
1> Task Parameter:File=myoutput.txt
1> Task Parameter:Lines=2019-02-21T163909
1> Task Parameter:Overwrite=True
1> Done executing task "WriteLinestoFile".
1>Done building target "test_BeforeTargets_BeforeBuild" in project "TestMSBuild.csproj".
When myinput.txt is not modified, but the .csproj is. I get the expected skipping of the target:
1>Target "test_BeforeTargets_BeforeBuild" in file "C:\Users\dan\source\repos\TestMSBuild\TestMSBuild.csproj":
1> Skipping target "test_BeforeTargets_BeforeBuild" because all output files are up-to-date with respect to the input files.
1> Input files: myinput.txt
1> Output files: myoutput.txt
1>Done building target "test_BeforeTargets_BeforeBuild" in project "TestMSBuild.csproj".
If I build twice without modifying anything, then modify only myinput.txt, I get a one-liner output, no matter how many times I try to build:
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
I expected that when I modify myinput.txt only, the target will not be skipped. Currently, this is only true if I also modify the .csproj file at the same time.
The following variations of BeforeTargets & AfterTargets were tried but to no avail:
BeforeTargets="BeforeBuild" (as above)
BeforeTargets="Build"
AfterTargets="BeforeBuild"
AfterTargets="Build"
I've only tried .NET-Core (Microsoft.NET.Sdk) and ASP.NET-Core (Microsoft.NET.Sdk.Razor & Microsoft.NET.Sdk.Web) projects but both have the same result.
Question:
How can I get this toy project working?
While the MSBuild-based up-to-date check works as expected, there is also an additional up-to-date check performed Visual Studio to determine if it should call MSBuild or not. Since it doesn't know about your input file, it determines that there is no need to run MSBuild on that project.
This can be changed by telling VS about it using the UpToDateCheckInput and UpToDateCheckOutput items that the project system uses for this check:
<ItemGroup>
<UpToDateCheckInput Include="#(MyInputs)" />
<UpToDateCheckOutput Include="#(MyOutputs)" />
</ItemGroup>

How do I get msbuild /restore to work for a standalone/non-SDK project file?

I want to use msbuild /restore with my project file. However, my project file is more like a script which orchestrates building multiple projects with particular properties, etc. Thus, it doesn’t make sense for me to set Sdk="Microsoft.NET.Sdk" because that causes weird errors to show up. However, if I don’t specify the Sdk, the /restore is ignored and it fails to actually restore anything.
Here is my example standalone project:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="RoslynCodeTaskFactory" Version="2.0.7" />
</ItemGroup>
<Target Name="Build">
<HelloWorld/>
</Target>
<UsingTask AssemblyFile="$(RoslynCodeTaskFactory)" Condition="'$(RoslynCodeTaskFactory)' != ''" TaskFactory="CodeTaskFactory" TaskName="HelloWorld">
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
Console.WriteLine("Hello, world!");
]]>
</Code>
</Task>
</UsingTask>
</Project>
My invocation and output:
C:\Users\binki\AppData\Local\Temp>"\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\MSBuild.exe" /restore helloworld.proj
Microsoft (R) Build Engine version 15.7.177.53362 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 2018-05-15 01:23:28.
Project "C:\Users\binki\AppData\Local\Temp\helloworld.proj" on node 1 (default targets).
C:\Users\binki\AppData\Local\Temp\helloworld.proj(8,5): error MSB4036: The "HelloWorld" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with <UsingTask> in the project file, or in the *.tasks files located in the "C:\Program Files 9x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64" directory.
Done Building Project "C:\Users\binki\AppData\Local\Temp\helloworld.proj" (default targets) -- FAILED.
Build FAILED.
"C:\Users\binki\AppData\Local\Temp\helloworld.proj" (default target) (1:2) ->
(Build target) ->
C:\Users\binki\AppData\Local\Temp\helloworld.proj(8,5): error MSB4036: The "HelloWorld" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with <UsingTask> in the project file, or in the *.tasks files located in the "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64" directory.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:01.71

Wix Variables defined on project properties Build tab are not being passed to candle

In by bundle.wxs I am trying to set a custom variable which is base on the configuration being built like this:
<Variable Name="SETTINGPROVIDERURL" Value="$(var.siteloc)"/>
I am trying to set "siteloc" on the Properties > build tab in the VS2017 project. I am trying both preprocessor and wixvariable to get at least one to come through.
in the wixproj file, I can see these:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<WixVariables>siteloc=bar;</WixVariables>
<DefineConstants>siteloc=foo;</DefineConstants>
</PropertyGroup>
When I build, I get CNDL0150: Undefined preprocessor variable '$(var.siteloc)'. As you can see, my variable (either one) was not added as a parameter to candle in the VS Console:
2>------ Build started: Project: KioskHostBootstrapper, Configuration: Release x86 ------
2> C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe -dBuildVersion=5.0.307.1 -d"DevEnvDir=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\\" -dSolutionDir=C:\centrics\CentricsStoreFront_5_0\Source\ -dSolutionExt=.sln -dSolutionFileName=CentricsStoreFront_5_0.sln -dSolutionName=CentricsStoreFront_5_0 -dSolutionPath=C:\centrics\CentricsStoreFront_5_0\Source\CentricsStoreFront_5_0.sln -dConfiguration=Release -dOutDir=bin\Release\ -dPlatform=x86 -dProjectDir=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostBootstrapper\ -dProjectExt=.wixproj -dProjectFileName=KioskHostBootstrapper.wixproj -dProjectName=KioskHostBootstrapper -dProjectPath=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostBootstrapper\KioskHostBootstrapper.wixproj -dTargetDir=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostBootstrapper\bin\Release\ -dTargetExt=.exe -dTargetFileName=KioskHostSetup.exe -dTargetName=KioskHostSetup -dTargetPath=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostBootstrapper\bin\Release\KioskHostSetup.exe -dKioskHostInstaller.Configuration=Release -d"KioskHostInstaller.FullConfiguration=Release|x86" -dKioskHostInstaller.Platform=x86 -dKioskHostInstaller.ProjectDir=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostInstaller\ -dKioskHostInstaller.ProjectExt=.wixproj -dKioskHostInstaller.ProjectFileName=KioskHostInstaller.wixproj -dKioskHostInstaller.ProjectName=KioskHostInstaller -dKioskHostInstaller.ProjectPath=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostInstaller\KioskHostInstaller.wixproj -dKioskHostInstaller.TargetDir=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostInstaller\bin\Release\ -dKioskHostInstaller.TargetExt=.msi -dKioskHostInstaller.TargetFileName=KioskHostInstaller.msi -dKioskHostInstaller.TargetName=KioskHostInstaller -dKioskHostInstaller.TargetPath=C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostInstaller\bin\Release\KioskHostInstaller.msi -out obj\Release\ -arch x86 -ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUtilExtension.dll" -ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixBalExtension.dll" Bundle.wxs
2>C:\centrics\CentricsStoreFront_5_0\Source\StoreFrontUtilities\KioskHost\WiXInstaller\KioskHostBootstrapper\Bundle.wxs(20,0): error CNDL0150: Undefined preprocessor variable '$(var.siteloc)'.
2>Done building project "KioskHostBootstrapper.wixproj" -- FAILED.
I tried this SF Suggestion,
<PropertyGroup>
<siteloc>fubar</siteloc>
</PropertyGroup>
but it didn't work.
What am I missing?

MSBuild-ing a VB Project with an InstallShield

I'm trying to create a MSBuild script that could build a VB project and an InstallShield Setup project.
Here's a BuildAll.XML file as the MSBuild script:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<MSBuild Projects="D:\WindowsApplication1\WindowsApplication1\WindowsApplication1.vbproj" />
<MSBuild Projects="D:\WindowsApplication1\Setup1\Setup1.isproj" />
</Target>
</Project>
Running this command on the Developer Command Prompt for VS2012.
msbuild.exe D:\WindowsApplication1\WindowsApplication1\BuildAll.xml /t:Build
The first MSBuild for the WindowApplication1.vbproc completes the build, but when the MSBuild would try to build the Setup1.isproj it fails.
Here's the warning and error:
"D:\WindowsApplication1\WindowsApplication1\BuildAll.xml" (Build
target) ( 1) -> "D:\WindowsApplication1\Setup1\Setup1.isproj" (default
target) (3) -> (Build target) -> C:\Program Files
(x86)\MSBuild\InstallShield\2013Limited\InstallShield.target s :
warning : -7235: InstallShield could not create the software
identification tag because the Tag Creator ID setting in the General
Information view is empt y.
[D:\WindowsApplication1\Setup1\Setup1.isproj] C:\Program Files
(x86)\MSBuild\InstallShield\2013Limited\InstallShield.target s :
warning : -1527: No files are included in the project. [D:\WindowsAppl
ication1\Setup1\Setup1.isproj]
"D:\WindowsApplication1\WindowsApplication1\BuildAll.xml" (Build
target) ( 1) -> "D:\WindowsApplication1\Setup1\Setup1.isproj" (default
target) (3) -> (Build target) -> C:\Program Files
(x86)\MSBuild\InstallShield\2013Limited\InstallShield.target s(108,3):
error : No outputs for project "WindowsApplication1" were provided, b
ut the installation project references
"WindowsApplication1.ContentFiles". [D:\
\WindowsApplication1\Setup1\Setup1.isproj] C:\Program Files
(x86)\MSBuild\InstallShield\2013Limited\InstallShield.target s(108,3):
error : No outputs for project "WindowsApplication1" were provided, b
ut the installation project references "WindowsApplication1.Built".
[D:\WindowsApplication1\Setup1\Setup1.isproj]
The Setup1 Project has two Application Files:
WindowsApplication1.ContentFiles
WindowsApplication1.PrimaryOutput
But when I use the Build > Build Solution on the Visual Studio 2012, it works fine. It produces the Setup.exe.
How can I make my BuildAll.xml make the same building process with the Visual Studio's Build Solution?
Got my answer from this post.
I should have built the entire solution rather than per project
Here's the correct script:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<MSBuild Projects="D:\WindowsApplication1\WindowsApplication1.sln" />
</Target>
</Project>

Why doesn't NAnt generate a bootstrapper file after calling MSBuild on a project?

I have a project with this in its MSBuild script:
<Target Name="AfterBuild">
<GenerateBootstrapper ApplicationFile="MyApp.msi" ApplicationName="My App" BootstrapperItems="#(BootstrapperFile)" OutputPath="$(OutputPath)" Culture="en-US" CopyComponents="true" ComponentsLocation="HomeSite" Path="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper" />
</Target>
If I run the project in visual studio, that gets run after the build and a setup.exe bootstrapper file is created in my bin/debug directory. However, if I build that same project (a WiX project, if that matters) under NAnt, everything gets built in the output directory that NAnt specifies, except the bootstrapper file. Nothing is being built in the project's bin/debug directory when I build it under NAnt, so the setup.exe file doesn't seem to be getting built, even there. I don't think that the AfterBuild step is even being run.
How can I generate this bootstrapper file under NAnt?
I had to specify the variable OutputPath in my NAnt script: