How To: Add Custom Process at Specific Points During Build (Method #2)

Back in November I wrote about a quick-and-dirty way to add custom build process into the standard Visual Studio build by overriding pre-defined targets that exist in Microsoft.Common.Targets. While this method works fine for internal build processes it can be brittle if you’re trying to deploy your build process to other teams or customers. In particular, if someone else decides to go and override the same target after you’ve done so, your customization will disappear. To handle this situation we’ve provided a second way of inserting your custom build process into the Visual Studio build: overriding properties that are used in TargetDependsOn attributes. The easiest way to understand how to do this is to look at a short snippet from Microsoft.Common.Targets:

<Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/>

Notice how the Build target has a DependsOnTargets that points to the BuildDependsOn property. That means before the Build target can run, all the targets listed in BuildDependsOn have to run first:

<PropertyGroup>

    <BuildDependsOn>

    BeforeBuild;

    CoreBuild;

    AfterBuild

    </BuildDependsOn>

</PropertyGroup>

If you want to add something to the build process that runs after everything else in the build, you’d simply create your own target and then add it to BuildDependsOn like this:

<PropertyGroup>

    <BuildDependsOn>

    $(BuildDependsOn);

    MyCustomTarget

    </BuildDependsOn>

</PropertyGroup>

<Target Name="MyCustomTarget">

    <Message Text="Hello from MyCustomTarget"/>

</Target>

Notice how we’ve included the original value of BuildDependsOn in our new definition of the property. Using this pattern means that anyone who overrides the existing meaning of BuildDependsOn will include all the existing content of the property, without overwriting customizations others have made. You can use a similar approach to get your custom target to run before everything in BuildDependsOn.

Here’s a list of the most commonly used *DependsOn properties:

Property Description
BuildDependsOn This is the property to use if you want to insert custom process before or after the entire build process. As you might guess, this is frequently used.
CleanDependsOn This is the property to override if you want to clean up output from your custom build process.
CompileDependsOn This is a very useful property as it provides a place to insert custom process before or after the compliation step. This is frequently overriden.

In addition to the three common properties there are many other properties that are almost never used. For completeness, here’s what they are and why you might use them:

Property Description
CompileLicxFilesDependsOn Targets in this property run before .licx files get compiled.
CoreBuildDependsOn This is the heavy-duty part of the build process and pretty much drives the whole build.
CoreCleanDependsOn This is really provided for design pattern completeness. There’s no real reason to use this instead of CleanDependsOn.
CoreCompileDependsOn Interestingly this is one of only two *DependsOn properties that are defined in the language-specific targets files instead of Microsoft.Common.Targets. This is rarely used; instead, override CompileDependsOn.
CreateManifestResourceNamesDependsOn Run before the manifest resource name is created from .resx files. Rarely overridden.
CreateSatelliteAssembliesDependsOn Primarily used as a way to force intermediate satellite assemblies to be computed before the final satellite assemblies are regenerated.
GetRedistListsDependsOn While this is in the Common.Targets file and can technically be used to insert custom process around the collection of redistributable assemblies, this is really there to ensure framework path resolution happens before the lists are gathered. I doubt anyone will ever need to override this.
PostBuildEventDependsOn This runs before the PostBuildEvent target is executed. This is rarely overridden since PostBuildEvent largely exists to support the legacy build extension methods offered in Visual Studio 2003 and earlier. Instead of overriding this you should consider using BuildDependsOn.
PreBuildEventDependsOn This runs before the PreBuildEvent target is executed. This is rarely overridden since PreBuildEvent largely exists to support the legacy build extension methods offered in Visual Studio 2003 and earlier. Instead of overriding this you should consider using BuildDependsOn.
PrepareForBuildDependsOn This takes care of getting all the build pre-requisites done before the actual build process starts. You can think of targets in this property as being almost like initialization routines for the whole build.
PrepareForRunDependsOn This is a good place to insert build process that needs to get content into place before the application is executed from within Visual Studio. Having said that, it’s rarely overridden.
PrepareResourceNamesDependsOn Prepares the names of the resource files before they get passed to the complication step of the build.
PrepareResourcesDependsOn Prepares the resources before they get passed to the compliation step of the build.
PublishBuildDependsOn The list of targets that must run before the project is published. Rarely, if ever, used. Instead, use PublishOnlyDependsOn.
PublishDependsOn Runs before the project is published using ClickOnce deployment outside of the IDE. It causes a build to happen before publish takes place. If you need to do work before the project is published you should override PublishOnlyDependsOn instead, since PublishDependsOn includes a call to PublishOnlyDependsOn.
PublishOnlyDependsOn Run after the IDE has completed a build and then needs to do a publish (as opposed to a command-line build where build followed by publish might happen all in one build command). If you need to do work before or after the project is published this is the property to use.
RebuildDependsOn This drives the rebuild target, and handles clean and then re-building the project. If you want to do something before or after rebuild this is the property to override.
ResGenDependsOn This is used to drive the resource generation step of the build process. If you need to do something before or after resource generation, this is the property to override.
ResolveAssemblyReferencesDependsOn This has a similar story to GetRedistListsDependsOn. It’s unlikely anyone will ever need to override this.
ResolveReferencesDependsOn This is the workhorse for resolving assembly references, one of the most complicated parts of the build process. If you want to do special work to handle assembly resolution, or do work immediately following the resolution of all the assembly references, this is the property to use. Having said that, it’s rarely overridden.
RunDependsOn Targets in this property will get executed before the compiled application is run.
UnmanagedRegistrationDependsOn Targets in this property are run before the main assembly is registered for COM interop.
UnmanagedUnregistrationDependsOn This runs before the main assembly is registered for COM interop purposes.
BuiltProjectOutputGroupDependsOnDebugSymbolsProjectOutputGroupDependsOnDocumentationProjectOutputGroupDependsOnSatelliteDllsProjectOutputGroupDependsOnSourceFilesProjectOutputGroupDependsOnContentFilesProjectOutputGroupDependsOn Targets in these properties are run before output groups are computed for the IDE.

[ Author: Neil Enns ]