在MSBuild中,我可以在MetaData项目上使用String.Replace函数吗?

wil*_*lem 34 msbuild

在MSBuild v4中,可以使用Propertiesstring.replace上的函数(如).但是我如何在元数据上使用函数?

我想使用如下string.replace功能:

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

不幸的是,这输出(不是我想要的): log4net.Replace(".config",""); ajaxPro.Replace(".config",""); appSettings.Replace(".config"," "); cachingConfiguration20.Replace("配置" "");.cmsSiteConfiguration.Replace( ""); dataProductsGraphConfiguration.Replace(" "配置".配置" "");.ajaxPro.Replace(".配置" , ""); appSettings.Replace( "配置", ""); cachingConfiguration20.Replace( "配置", ""); cmsSiteConfiguratio

有什么想法吗?

Gra*_*ers 59

你可以用一点点诡计来做到这一点:

$([System.String]::Copy('%(Filename)').Replace('config',''))
Run Code Online (Sandbox Code Playgroud)

基本上,我们调用静态方法'Copy'来创建一个新字符串(由于某种原因,如果你只是尝试它不喜欢它$('%(Filename)'.Replace('.config',''))),然后调用字符串上的replace函数.

全文应如下所示:

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

编辑: MSBuild 12.0似乎打破了上述方法.作为替代方案,我们可以向所有现有Files项添加新的元数据条目.我们在定义元数据项时执行替换,然后我们可以像任何其他元数据项一样访问修改后的值.

例如

<?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>
Run Code Online (Sandbox Code Playgroud)

结果:

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).
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用$([MSBuild] :: ValueOrDefault('%(MetadataName)','').Replace('foo','bar'))`代替String.Copy,以避免实际创建字符串数据的副本。 (3认同)
  • 有关信息:MSBuild 的 GitHub 存储库上有一个相关的未解决问题:[元数据应支持实例方法](https://github.com/microsoft/msbuild/issues/1155)。 (3认同)
  • 使用msbuild 12.0(和.net 4.0)我得到“%(Filename);%(Filename);..”结果。我的环境出了什么问题? (2认同)

小智 27

我需要做类似的事情,以下对我有用.

<Target Name="Build">
  <Message Text="@(Files->'%(Filename)'->Replace('.config', ''))" />
</Target>
Run Code Online (Sandbox Code Playgroud)

  • 这看起来是最简洁的答案。 (2认同)
  • 这对我来说似乎是最好的答案。简短而甜蜜。 (2认同)
  • 这利用了 MSBuild 项函数,我认为这是最干净、最惯用的。它也不会像替代方案那样引起字符串复制。了解更多信息,请访问 https://learn.microsoft.com/en-us/visualstudio/msbuild/item-functions (2认同)

Ser*_*kov 18

这些功能仅适用于属性(据我所知).因此创建将执行操作抛出批处理的目标:

<Target Name="Build"                                 
      DependsOnTargets="ProcessFile" />

<Target Name="ProcessFile"
       Outputs="%(Files.Identity)">
   <PropertyGroup>
       <OriginalFileName>%(Files.Filename)</OriginalFileName>
       <ModifiedFileName>$(OriginalFileName.Replace(".config",""))</ModifiedFileName>
   </PropertyGroup>
   <Message Text="$(ModifiedFileName)" Importance="High"/>
</Target>
Run Code Online (Sandbox Code Playgroud)

在你的例子中你真的需要这样的任务吗?我的意思是存在MSBuild着名的项元数据

编辑:我应该指定此任务处理@(文件)中的所有项目.

  • 不怕:( Files.FileName 是一个集合,但 $ModifiedFileName 最终只是一个值。我需要对“文件”中的每个项目运行“替换”。 (2认同)