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

时间:2011-02-24 09:58:56

标签: msbuild

在MSBuild v4中,可以在属性上使用函数(如string.replace)。但是如何在元数据上使用函数?

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

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

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

有什么想法吗?

6 个答案:

答案 0 :(得分:51)

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

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

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

全文应如下所示:

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

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

<强> 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>

结果:

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).

答案 1 :(得分:22)

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

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

答案 2 :(得分: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>

你真的需要在你的例子中做这样的任务吗?我的意思是存在MSBuild Well-known Item Metadata

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

答案 3 :(得分:1)

对于MSBuild 12.0,这是另一种选择。

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

答案 4 :(得分:0)

我认为你不能直接使用项目组和元数据功能(这很容易) 但是您可以使用批处理:

从这篇文章中获取想法: array-iteration

我试图修剪一个项目组以发送到命令行工具(我需要丢失.server文件名)

<Target Name="ProcessFile"  DependsOnTargets="FullPaths">

    <ItemGroup>
        <Environments Include="$(TemplateFolder)\$(Branch)\*.server.xml"/>
    </ItemGroup>

    <MSBuild Projects=".\Configure.msbuild" 
             Properties="CurrentXmlFile=%(Environments.Filename)"
             Targets="Configure"/>

</Target>

<Target Name="Configure" DependsOnTargets="FullPaths">
    <PropertyGroup>
        <Trimmed>$(CurrentXmlFile.Replace('.server',''))</Trimmed>
    </PropertyGroup>

    <Message Text="Trimmed: $(Trimmed)"/>

    <Exec  Command="ConfigCmd $(Trimmed)"/>
</Target>

答案 5 :(得分:0)

遇到了同样的问题(除了使用MakeRelative),所以我传递了另一个解决方案:使用带有字符串并转换为Item的旧旧CreateItem:)

        <ItemGroup>
            <_ToUploadFTP Include="$(PublishDir)**\*.*"></_ToUploadFTP>
        </ItemGroup>
        <CreateItem Include="$([MSBuild]::MakeRelative('c:\$(PublishDir)','c:\%(relativedir)%(filename)%(_ToUploadFTP.extension)'))">
            <Output ItemName="_ToUploadFTPRelative" TaskParameter="Include"/>
        </CreateItem>
        <FtpUpload Username="$(UserName)" 
                   Password="$(UserPassword)" 
                   RemoteUri="$(FtpHost)"
                   LocalFiles="@(_ToUploadFTP)"
                   RemoteFiles="@(_ToUploadFTPRelative->'$(FtpSitePath)/%(relativedir)%(filename)%(extension)')"
                   UsePassive="$(FtpPassiveMode)" ></FtpUpload>