Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In MSBuild, can I use the String.Replace function on a MetaData item?

Tags:

msbuild

In MSBuild v4 one can use functions (like string.replace) on Properties. But how can I use functions on Metadata?

I'd like to use the string.replace function as below:

<Target Name="Build">         <Message Text="@(Files->'%(Filename).Replace(&quot;.config&quot;,&quot;&quot;)')" /> </Target>    

Unfortunately this outputs as (not quite what I was going for): log4net.Replace(".config","");ajaxPro.Replace(".config","");appSettings.Replace(".config","");cachingConfiguration20.Replace(".config","");cmsSiteConfiguration.Replace(".config","");dataProductsGraphConfiguration.Replace(".config","");ajaxPro.Replace(".config","");appSettings.Replace(".config","");cachingConfiguration20.Replace(".config","");cmsSiteConfiguratio

Any thoughts?

like image 546
willem Avatar asked Feb 24 '11 09:02

willem


1 Answers

You can do this with a little bit of trickery:

$([System.String]::Copy('%(Filename)').Replace('config','')) 

Basically, we call the static method 'Copy' to create a new string (for some reason it doesn't like it if you just try $('%(Filename)'.Replace('.config',''))), then call the replace function on the string.

The full text should look like this:

<Target Name="Build">         <Message Text="@(Files->'$([System.String]::Copy(&quot;%(Filename)&quot;).Replace(&quot;.config&quot;,&quot;&quot;))')" /> </Target> 

Edit: MSBuild 12.0 seems to have broken the above method. As an alternative, we can add a new metadata entry to all existing Files items. We perform the replace while defining the metadata item, then we can access the modified value like any other metadata item.

e.g.

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">      <ItemGroup>         <Files Include="Alice.jpg"/>         <Files Include="Bob.not-config.gif"/>         <Files Include="Charlie.config.txt"/>     </ItemGroup>      <Target Name="Build">         <ItemGroup>             <!--              Modify all existing 'Files' items so that they contain an entry where we have done our replace.             Note: This needs to be done WITHIN the '<Target>' (it's a requirment for modifying existing items like this             -->             <Files>                 <FilenameWithoutConfig>$([System.String]::Copy('%(Filename)').Replace('.config', ''))</FilenameWithoutConfig>             </Files>         </ItemGroup>          <Message Text="@(Files->'%(FilenameWithoutConfig)')" Importance="high" />     </Target> </Project> 

Result:

D:\temp>"c:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" /nologo test.xml Build started 2015/02/11 11:19:10 AM. Project "D:\temp\test.xml" on node 1 (default targets). Build:   Alice;Bob.not-config;Charlie Done Building Project "D:\temp\test.xml" (default targets). 
like image 77
Grant Peters Avatar answered Sep 22 '22 04:09

Grant Peters