MSBuild: Run target after solution builds from within Visual Studio

GalaxyInvader picture GalaxyInvader · Apr 19, 2015 · Viewed 9.5k times · Source

We have a solution with several projects in it, and need to run a tool on our compiled code after all of our code is compiled. The tool must take, as input, all .dll and .exe files built from the solution (so for an incremental build, it is not enough to give it only the just-rebuilt binaries), and all of those binaries must be up to date.

Right now we do this with an MSBuild .proj file that we run from the a command line, which includes all projects and uses the Output element of MSBuild to find the paths to the binaries in the solution.

This has two problems that make this solution not quite fit what we need. The tool does not need to actually be run on all projects, only some of them. And it's required that we be able to build from within Visual Studio.

It seems like what I need is, in some projects' .csproj files, to define something that says "run the tool on me", to collect those project's paths, and to run the tool on that collection of paths.

But I can't see how to do this. It looks like when I build from Visual Studio, I cannot share state between project builds, and it looks like there is no hook for after the solution builds.

From the command line, there are before.*.sln.targets and after.*.sln.targets, but these do not work from Visual Studio.

It seems like what I want is ridiculously simple, I just want a tool to automatically look at the solution's binaries after a build, so I do not think this should be impossible. But I can't see how to do this from the documentation. I am new to MSBuild, so I am probably missing something obvious.

Answer

Atilla Ozgur picture Atilla Ozgur · Apr 19, 2015

Msbuild has extensibility targets. These empty targets can be used in project files. See following article and section Build process extensibility points.

For instance, if you wanted to deploy some related files alongside the assembly once it was built, overriding the AfterBuild target would be the way to go, as shown below.

I changed their example to use exec task as below. This example use YourCustomTasks.exe on your binary files after they are built.

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <!-- Properties and items are deleted for clarity -->
    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    <ItemGroup>
        <Binaries Include="*.dll;*.exe"/>
    </ItemGroup>
    <Target Name="AfterBuild">
        <Exec Command="YourCustomTasks.exe %(Binaries.Identity)" />
    </Target>
</Project>

If you want your target to work after your solution, use following answer.

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