Don't be afraid of your csproj-Files (II): Add Your own Targets

In my first post on csproj-fun I had an example where after every build, the resulting assemblies lying in e.g. bin/debug would be merged into one and copied out to some other place. Maybe you do not want this every time you rebuild your project, but you’d rather want to trigger it at will.

The only thing you need to do is to place the tasks in the AfterBuild target into some different target, like so:

  <Target Name="Merge" [DependsOnTarget="Build"]>
    ...
    <ILMerge InputAssemblies="@(DllOutput)" ... />
  </Target>

This target will now reside in your csproj file, and indeed Visual Studio would merely change the location within the file, if anything. The Visual Studio compile run will not bother with your Target. No build-relevant task depends on it. If you wish, you can make your new Target depend on the build. That way your project will be built before your target is executed.

Question is, how can you put your new target to use?

Sadly, Visual Studio has no direct support of Targets defined in a csproj that are not connected to the build process. What you can do is to use the VS200x command prompt, go to the folder that contains the csproj file and type

msbuild /t:Merge

Not too bad, but still somewhat clumsy. A more comfortable and integrated way to call your target is to do the following:

  1. Under Visual Studio/Tools choose “External Tools…”

  2. Press Add and fill out the dialog as shown in this screenshot: Note that msbuild is found in any framework directory. Also note that the used variable will become the directory of the project currently selected in the solution explorer.

  3. Now your newly created command will appear in the Tools Menu. By selecting your new command, the following dialog appears: Here you can type your arguments, i.e. calling a specific target. The checkbox we chose to see the output gives us a nice output in the corresponding Visual Studio window. Just as a reminder, you can parameterize your MSBuild task. You can then pass parameters through the command line arguments as such:

/p:Var1=AAA;Var2=BBB 

Admittedly, I would prefer a solution that is part of Visual Studio. I would like to right-click on a project file in the solution explorer and enter the submenu “Targets” (which only exists if there are custom targets in the csproj file) and choose “Merge” in this case.

However, this works fairly well and allows me to zip, merge, generate and do all things MSBuild does from custom tasks safely tucked into my csproj file.

btw, don’t forget to document your additions! You may forget the target name…