I just wrote the answer to this question http://sedodream.com/2012/07/28/MSBuildHowToExecuteATargetAfterCoreCompilePart2.aspx , but I inserted this solution below.
A few months ago, I wrote an MSBuild blog post about how to complete a task after CoreCompile , in which I describe how you can accomplish a goal, if the goal of CoreCompile is fulfilled, if CoreCompile is skipped, then your other goal. The rollback of the approach that I outlined in a previous post was that it required you to edit the .csproj / .vbproj / etc file yourself. Therefore, if you had a script to create several projects, you will have to edit all the project files. In this post, I describe how you can perform the same setup without editing the project file itself.
Before we get to the solution for this particular case, let me describe the extensibility hook that C # and VB projects have. Most of the logic for building C # and VB projects is captured in the MSBuild targets file in C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.Common.targets. If you look in this file, you will see an import at the top similar to the one below.
<Import Project="$(CustomBeforeMicrosoftCommonTargets)" Condition="'$(CustomBeforeMicrosoftCommonTargets)' != '' and Exists('$(CustomBeforeMicrosoftCommonTargets)')"/>
This statement will import the file (located by value for CustomBeforeMicrosoftCommonTargets) if the property is not empty and the file exists. The default value for CustomBeforeMicrosoftCommonTargets is C: \ Program Files (x86) \ MSBuild \ v4.0 \ Custom.Before.Microsoft.Common.targets. Therefore, if you delete the MSBuild file at this location, it will change the build process for each C # / VB project built on this computer. Alternatively, if you do not want (or cannot because of the ACL), you can delete the file elsewhere and then specify its location by overriding the CustomBeforeMicrosoftCommonTargets property. This is the approach that I will take here. I created a sample solution consisting of two projects, ProjA and ProjB. I also have a build script, build.proj to automate the build for this. Below is the full contents of build.proj.
build.proj
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <FileToInject Condition=" '$(FileToInject)'=='' ">$(MSBuildThisFileDirectory)extend-corecompile.proj</FileToInject> </PropertyGroup> <ItemGroup> <ProjectsToBuild Include="ProjA\ProjA.csproj"/> <ProjectsToBuild Include="ProjB\ProjB.csproj"/> </ItemGroup> <Target Name="Build"> <MSBuild Projects="@(ProjectsToBuild)" Properties="CustomBeforeMicrosoftCommonTargets=$(FileToInject)" /> </Target> <Target Name="Clean"> <MSBuild Projects="@(ProjectsToBuild)" Targets="Clean"/> </Target> <Target Name="Rebuild" DependsOnTargets="Clean;Build"/> </Project>
In the Build task above, I use the MSBuild task to create both ProjA and ProjB. As you can see, I am passing the CustomBeforeMicrosoftCommonTargets = $ (FileToInject) property, which points to the extension-corecompile.proj. Passing this property when building ProjA and ProjB, it automatically imports the extend-corecompile.proj file for the build process. Below you can see the contents of extend-corecompile.proj.
extend-corecompile.proj
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <TargetsTriggeredByCompilation> $(TargetsTriggeredByCompilation); MyCustomTarget </TargetsTriggeredByCompilation> </PropertyGroup> <Target Name="MyCustomTarget"> <Message Text="MyCustomTarget called" Importance ="high"/> </Target> </Project>
This project file uses the method described in my previous blog post to execute MyCustomTarget only if CoreCompile is running.
Note. You can get the latest version of this example at https://github.com/sayedihashimi/sayed-samples/tree/master/ExtBuildMultiple .