13

In other words, I want this Target to be invoked just once a the start and end of the whole build session, not for each individual project that might be built as part of that session.

Another way to put is it that when hitting Build (F7) in Visual Studio I would like to invoke my custom Target at the very beginning and end of the build, regardless of what was built (and whether or not it was successful).

Is this possible? If not, are there alternatives to using MSBuild Targets that would allow me to call my process at the start and end of every Visual Studio build?

Ben
  • 1,321
  • 15
  • 30
  • possible duplicate of [run MsBuild tasks (targets?) after the solution is built?](http://stackoverflow.com/questions/1649649/run-msbuild-tasks-targets-after-the-solution-is-built) – jessehouwing Jul 17 '13 at 21:51
  • 1
    I'm not sure it is a duplicate really - I want to invoke something before the build starts as well as at the end. There's some overlap, but this question appears to have garnered a very different approach in the answers. – Ben Jul 19 '13 at 13:54

1 Answers1

28

To execute a solution-wide Before and After targets, you would create two MSBuild project files named "after.<SolutionName>.sln.targets" and "before.<SolutionName>.sln.targets" in the same folder as your solution.

To do this on all solutions, you would drop your custom solution-level after targets files into the path $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportBefore\ or $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportAfter. When those solutions are built, it will import all project files in these folders if they exist.

To verify the above, open a command prompt and navigate to the folder containing your solution file. Type "SET MSBuildEmitSolution=1". Then run msbuild.exe <SolutionName>. You will see that msbuild has saved the metadata project files <SolutionName>.sln.metaproj and <SolutionName>.sln.metaproj.tmp in the same path as your solution.

View the <Import /> declarations at the top and bottom of the file and you'll notice the conditional imports that allow you to declare solution-specific before and after targets, or global solution-specific before and after targets.

Edit:

It appears that this would only be applicable to command line or team builds, but not from within Visual Studio.

I added this to my After.Solution.sln.targets file:

<Target Name="Banana" AfterTargets="Build">
    <Message Text="*** BEGIN BANANA ***" Importance="high" />
    <Message Text=" _                                          " Importance="high" />
    <Message Text="//\                                         " Importance="high" />
    <Message Text="V  \                                        " Importance="high" />
    <Message Text=" \  \_                                      " Importance="high" />
    <Message Text="  \,'.`-.                                   " Importance="high" />
    <Message Text="   |\ `. `.                                 " Importance="high" />
    <Message Text="   ( \  `. `-.                        _,.-:\" Importance="high" />
    <Message Text="    \ \   `.  `-._             __..--' ,-';/" Importance="high" />
    <Message Text="     \ `.   `-.   `-..___..---'   _.--' ,'/ " Importance="high" />
    <Message Text="      `. `.    `-._        __..--'    ,' /  " Importance="high" />
    <Message Text="        `. `-_     ``--..''       _.-' ,'   " Importance="high" />
    <Message Text="          `-_ `-.___        __,--'   ,'     " Importance="high" />
    <Message Text="             `-.__  `----'''    __.-'       " Importance="high" />
    <Message Text="                  `--..____..--'            " Importance="high" />
    <Message Text="*** END BANANA ***"  Importance="high" />
</Target>

From the command line: Bananas!

On a TFS build: Bananas!

Visual Studio: No bananas :(

Nicodemeus
  • 4,005
  • 20
  • 23
  • The full lowdown is here: http://sedodream.com/2010/10/22/MSBuildExtendingTheSolutionBuild.aspx. It's important to know about the Solution-level targets (Build, Rebuild, Clean & Publish) too, otherwise you can't trigger any of your own targets. – Ben Jul 19 '13 at 15:04
  • Actually this doesn't give me what I want. It only works if you build your VS solution by running MSBuild.exe explicitly. If you choose Build (or hit F7, say) in Visual Studio, these before and after targets files aren't used. – Ben Jul 19 '13 at 15:17
  • 2
    Well heck... according to this article, those extension points are not available from within visual studio :( http://connect.microsoft.com/VisualStudio/feedback/details/782934/visual-studio-not-executing-before-or-after-solution-file-targets – Nicodemeus Jul 19 '13 at 22:13
  • 1
    The banana rocks the suburbs ! ASCII art in my msbuild proj files, why didn't I think of this???? – granadaCoder Apr 20 '15 at 18:57
  • [3rd party VS extension CommonSolutionTargets](https://marketplace.visualstudio.com/items?itemName=KonstantinErman.CommonSolutionTargets) makes possible to run before and after sln from VS. – xmedeko Apr 20 '18 at 11:37
  • keep in mind that you will not be getting "Bananas" if you start your build with "-target:Rebuild" flag. In this case you should use: AfterTargets="Rebuild". Anyone knows how to universally trigger solution scope targets for Build or Rebuild? – Tenek May 17 '20 at 18:21
  • 1
    Never having created a targets file, I needed the initial `` line and its closing. You might add that to the answer for completeness. – StayOnTarget Jun 02 '20 at 19:50
  • @Tenek it's probably a bit late now but I think you would use AfterTargets="Build;Rebuild" – Bill Richards Feb 22 '22 at 16:28