2011-02-24 36 views
23

在MSBuild v4中,可以使用的功能(如string.replace)属性。但是,如何使用元数据上的功能?在MSBuild中,我可以使用MetaData项目上的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(”。 config“,”“); cmsSiteConfiguratio

有什么想法?

+0

你究竟在努力完成什么?希望最终结果是从项目组中的项目中删除扩展名吗?您可能想要将其作为创建来自修改条目的原始项目组的新项目组。如果需要更多的控制,转换或自定义任务可以做到这一点。 – 2011-02-24 16:57:05

+0

嗨。你最终解决了这个问题吗?怎么样?我有一个类似的问题:属性定义不起作用,因为Target将文件列表作为输入,而不是单个文件名。 – superjos 2011-11-08 10:05:26

回答

15

这些函数只在属性中工作(据我所知)。因此创建将执行操作投掷配料的目标:

<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

编辑:我应该指定这个任务处理所有项目在@(文件)。

+0

我不知道你可以根据另一个属性创建一个属性。非常非常有用! – willem 2011-02-24 10:50:27

+0

它解决了你的问题吗? – 2011-02-24 11:14:54

+1

不怕:(Files.FileName是一个集合,但$ ModifiedFileName最终只有一个值,我需要在“文件”中的每个项目上运行“替换” – willem 2011-02-24 11:40:52

0

我不认为你可以直接与itemgroups和元数据(这将是容易)使用功能 但是你可以用配料:

从这个帖子以思想: array-iteration

我试图裁剪的ItemGroup发送到一个命令行工具(我需要失去.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> 
45

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

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

基本上,我们调用静态方法“复制”来创建一个新的字符串(由于某种原因,它不喜欢它,如果你只是尝试$('%(Filename)'.Replace('.config',''))),然后调用的字符串替换功能。

全文应该是这样的:

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

编辑:的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> 

结果:

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

上面的例子似乎不起作用 – 2013-08-15 17:00:45

+1

它工作正常,谢谢! – 2013-10-15 20:34:22

+0

使用msbuild 12.0(和.net 4.0)我得到“%(Filename);%(Filename); ..”作为结果。我的环境有什么问题? – nilleb 2015-01-07 09:57:56

0

得到了同样的问题(除了MakeRelative),所以我用另一种解决方案通过:使用好老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> 
1

对于MSBuild 12.0,这里有一个选择。

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

我需要做类似的事情,以下工作适合我。

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

这看起来是最简洁的答案。 – Thomson 2015-02-11 03:22:37

+1

这看起来对我来说是最好的答案。简短而甜美。 – 2015-08-13 01:00:51

相关问题