Search code examples
msbuildcsproj

Get wildcard reference in csproj node


Take the following example:

<EmbeddedResource Include="Resources\files\main-*.png">
   <LogicalName>Images\main\???.resources</LogicalName>
</EmbeddedResource>

How can I get the part from "*" inside a child of a node? I have found %Filename%, but that's too much.


Solution

  • It is possible, but requires some property functions kung fu.

    <Project>
        <!--
            Create files:
            Resources\files\main-foo.png
            Resources\files\main-bar.png
    
            Run:
            MSBuild.exe foo.proj /t:Test
    
            Output:
            LogicalName: Images\main\foo.resources
            LogicalName: Images\main\bar.resources
        -->
    
        <ItemGroup>
            <EmbeddedResource Include="Resources\files\main-*.png">
                <_DashPosition>$([System.String]::Copy('%(FileName)').IndexOf('-'))</_DashPosition>
                <_LogicalNameStart>$([MSBuild]::Add(%(_DashPosition), 1))</_LogicalNameStart>
                <LogicalName>Images\main\$([System.String]::Copy('%(FileName)').Substring(%(_LogicalNameStart))).resources</LogicalName>
            </EmbeddedResource>
        </ItemGroup>
    
        <Target Name="Test">
            <Message Text="LogicalName: %(EmbeddedResource.LogicalName)" Importance="high"/>
        </Target>
    
    </Project>
    

    The general approach is like it would be in C# or other language. Find the delimiter (here - in the filename) and take everything after that as LogicalName.

    Note that I used "temporary" item metadata (the '_' is just a convention here) to keep things a little more clear. In theory, you could cramp all into the <LogicalName> itself.