Question

I can create MSBuild property, which contain unexpanded property reference. Here is example of it:

Text file property.txt contains single line

$(SomeProperty)

It can be processed with msbuild script like this:

<ItemGroup>
  <PropertyFile Include="property.txt"/>
</ItemGroup>

<!-- Standart task for file reading -->
<ReadLinesFromFile File="@(PropertyFile)" >
  <Output
      TaskParameter="Lines"
      ItemName="ItemsFromFile"/>
</ReadLinesFromFile>

<!-- Property LastLine now has value $(SomeProperty) -->
<PropertyGroup>
  <LastLine>%(ItemsFromFile.Identity)</LastLine>     
</PropertyGroup>

<Message Text="$(LastLine)"/>

Now I want to expand property reference, which contains in CurrentLine. Is it possible?

Was it helpful?

Solution

If you know in advance all of the properties that are candidates for being the single property listed in the file there is a way to do this with item filtering. Caveats:

1) Specify only the PropertyName in the file, not $(PropertyName), unless you want to parse the string using a property function.

2) There can only be a single line in the file with the approach below, for multiple lines you'll need an extra level of batching.

<ItemGroup>
  <PropertyFile Include="property.txt" />
</ItemGroup>

<PropertyGroup>
  <SomeProperty>1</SomeProperty>
  <SomeOtherProperty>2</SomeOtherProperty>
</PropertyGroup>
<ItemGroup>
  <ChooseProperty Include="SomeProperty">
    <Value>$(SomeProperty)</Value>
  </ChooseProperty>
  <ChooseProperty Include="SomeOtherProperty">
    <Value>$(SomeOtherProperty)</Value>
  </ChooseProperty>
</ItemGroup>

The constructs above establish two candidate properties, $(SomeProperty) and $(SomeOtherProperty). For this example the contents of property.txt was a single line...

SomeProperty

...which correlates to $(SomeProperty) which has a value of 1

<Target Name="ReadItems">
  <ReadLinesFromFile File="@(PropertyFile)">
    <Output
      TaskParameter="Lines"
      ItemName="ItemsFromFile"
      />
  </ReadLinesFromFile>
</Target>

<Target Name="FilterItems"
  Outputs="%(ChooseProperty.Identity)">
  <PropertyGroup>
    <_ThisProperty>%(ChooseProperty.Identity)</_ThisProperty>
    <_ThisValue>%(ChooseProperty.Value)</_ThisValue>
    <_ItemFromFile>%(ItemsFromFile.Identity)</_ItemFromFile>
  </PropertyGroup>
  <ItemGroup Condition="'$(_ItemFromFile)' == '$(_ThisProperty)'">
    <_FilteredItems Include="$(_ThisProperty)">
      <Value>$(_ThisValue)</Value>
    </_FilteredItems>
  </ItemGroup>
</Target>

Above are the two dependent targets for the main target below. They use a dependent target to read the file so that it is published into an item group to be used with target batching on the @(ChooseProperty) item group. The key thing to note is the condition on the creation of the @(_FilteredItems) item group, which will contain a single member, due to this...

Condition="'$(_ItemFromFile)' == '$(_ThisProperty)'

...notice that the batched item meta data is transferred to these temporary properties in order to make the condition work (and this is why the file can only contain a single line, so that there is only a single item).

<Target Name="ChoosePropertyFromItem"
  DependsOnTargets="ReadItems;FilterItems">
  <!-- Standard task for file reading -->
  <PropertyGroup>
    <LastLine>%(_FilteredItems.Value)</LastLine>
  </PropertyGroup>
  <Message Text="LastLine='$(LastLine)'" />
</Target>

...finally the $(LastLine) Property is pulled from the single item in @(_FilteredItems). The resulting output is below:

ChoosePropertyFromItem:
  LastLine='1'

Changing the property.txt to contain 'SomeOtherProperty' results in this:

ChoosePropertyFromItem:
  LastLine='2'

OTHER TIPS

You can't create new properties in such a way. You can't create property names dynamically. You can modify build process. Example

 msbuild.exe yourproject.sln /p:UseSomeProp=true
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top