Using the contents of a file to define an MSBuild property

Raymond Chen

Say you want to define a property in your MSBuild project file (vcxproj, csproj, etc.) and have the property value come from a file. You might try using the Read­Lines­From­File task to get the contents:

  <Target Name="DefineMagic">
    <ReadLinesFromFile File=".\magic.txt">
      <Output TaskParameter="Lines" PropertyName="Magic" />
    </ReadLinesFromFile>
  </Target>
  <ItemDefinitionGroup>
    <ClCompile>
      <PreprocessorDefinitions>MAGIC="$(Magic)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
  </ItemDefinitionGroup>

This doesn’t work because the Target doesn’t run until after the Item­Definition­Group is already defined. MSBuild evaluates Property­Group and Item­Group elements before running any Targets, By the time you execute the Read­Lines­From­File task, it’s too late.

Instead, you can use the Read­All­Text MSBuild property function to read the text into a property.

  <PropertyGroup>
    <Magic>$([System.IO.File]::ReadAllText('.\magic.txt').TrimEnd())</Magic>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <ClCompile>
      <PreprocessorDefinitions>MAGIC="$(Magic)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
  </ItemDefinitionGroup>

You can see an example of this trick in the WindowsAppSDK build properties.