With MSBuild 3.5 two new known metadata names were introduced for items passed to the MSBuild Task. Those known metadata names are Properties and AdditionalProperties. The idea is that you can now specify properties on the item itself instead of having to pass all the properties using the Properties attribute on the MSBuild Task. For example you could define an item, Projects, to be:


    <Projects Include="Project01.proj">



Then you can build the values contained in the Projects item using the MSBuild task:

<Target Name="BuildProjects">

    <MSBuild Projects="@(Projects)"/>



Like I said previously there are two new ways to pass properties in item metadata, Properties and AdditionalProperties. The difference can be confusing and very problematic if used incorrectly. Admittedly I didn't know the difference until about 6 months ago (but soon enough to include in my book J ). The difference is that if you specify properties using the Properties metadata then any properties defined using the Properties attribute on the MSBuild Task will be ignored. In contrast to that if you use the AdditionalProperties metadata then both values will be used, with a preference going to the AdditionalProperties values.

Now let's take a look at an example to make this clear. The following MSBuild file is named Properties.proj and is shown below.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">







     <_ProjectToBuild_Properties Include="$(ProjectPath)">





    <_ProjectToBuild_AdditionalProperties Include="$(ProjectPath)">





<Target Name="Build_Properties">

    <Message Text="Building project with Properties metadata" Importance="high"/>

    <MSBuild Projects="@(_ProjectToBuild_Properties)" Properties="DebugSymbols=true" />



<Target Name="Build_AProperties">

    <Message Text="Building project with AdditionalProperties metadata" Importance="high"/>

    <MSBuild Projects="@(_ProjectToBuild_AdditionalProperties)" Properties="DebugSymbols=true" />




I've highlighted a few important elements contained in this file. Firstly if you do not specify your ToolsVersion to be 3.5 then none of this functionality will work. Make sure to always provide this value, or you may be baffled by the un-expected behavior.

Inside of both targets you can see that I and providing the value Properties="DebugSymbols=true". Below is the definition of the file that it is building, the Project01.proj file.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">


<Target Name="Build">

    <Message Text="Building $(MSBuildProjectFile)" Importance="high"/>

    <Message Text="Configuration: $(Configuration)"/>

    <Message Text="DebugSymbols: $(DebugSymbols)"/>

    <Message Text="OutputPath: $(OutputPath)"/>




This file just prints out the values for a couple of properties that are not defined inside the file itself. Now let's see the behavior when we execute both of these targets. The result is shown in the image below.

As I've highlighted here the result of executing the Build_Properties target results in the attribute Properties="DebugSymbols=true" being completely ignored. The result from the Build_AProperties target takes the Properties attribute into consideration as well as the AdditionalProperties metadata. Don't use both of these together!

I personally prefer using the AdditionalProperties because I think that ignoring the Properties attribute can be confusing and hard to diagnose. This is why I tend to use that approach instead of the Properties metadata unless I have a specific reason.

Sayed Ibrahim Hashimi




Comment Section

Comments are closed.