首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >修改MSBuild ItemGroup元数据

修改MSBuild ItemGroup元数据
EN

Stack Overflow用户
提问于 2009-05-08 21:34:35
回答 6查看 22.6K关注 0票数 25

ItemGroup的元数据是否可以在声明后进行修改。

例如:

代码语言:javascript
复制
  <ItemGroup>
    <SolutionToBuild Include="$(BuildProjectFolderPath)\MySolution.sln">
      <Targets></Targets>
      <Properties></Properties>
    </SolutionToBuild>

  </ItemGroup>

  <Target Name="BuildNumberOverrideTarget">
     <!--Code to get the version number from a file (removed)-->

     <!--Begin Pseudo Code-->
     <CodeToChangeItemGroupMetaData 
           ItemToChange="%(SolutionToBuild.Properties)" 
           Condition ="'%(SolutionToBuild.Identity)' ==
                       '$(BuildProjectFolderPath)\MySolution.sln'"
           NewValue="Version=$(Version)" />
     <!--End Pseudo Code-->         

  </Target>

我希望有一种方法,不需要我删除项目,然后重新声明它。

谢谢你的回答。瓦卡诺

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-05-11 18:09:14

为此,我必须编写一个自定义任务:

下面是它的工作原理

代码语言:javascript
复制
<ItemGroup>
  <ItemsToChange Include="@(SolutionToBuild)">
    <Properties>ChangedValue</Properties>
  </ItemsToChange>
  <MetaDataToChange Include="Properties"/>
</ItemGroup>

<UpdateMetadata SourceList="@(SolutionToBuild)" ItemsToModify="@(ItemsToChange)" MetadataToModify="@(MetaDataToChange)">
  <Output TaskParameter="NewList" ItemName="SolutionToBuildTemp" />
</UpdateMetadata>

<ItemGroup>
  <SolutionToBuild Remove="@(SolutionToBuild)"/>
  <SolutionToBuild Include ="@(SolutionToBuildTemp)"/>
</ItemGroup>

它用更改后的值填充一个名为SolutionToBuildTemp的新项。然后,我删除SolutionToBuild项中的所有内容,并用SolutionToBuildTemp项填充它。

如果有人感兴趣,这里是任务的代码(我也提交给了MSBuildExtenstionPack )。

代码语言:javascript
复制
// By Stephen Schaff (Vaccano).  
// Free to use for your code. Need my Permission to Sell it.
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace UpdateMetadata
{
    ///<summary>
    /// Used to update the metadata in a ItemGroup (Note: Requires an MSBuild Call After using this task to complete the update.  See Usage.)
    /// Usage:
    /// &lt;?xml version="1.0" encoding="utf-8"?&gt;
    ///&lt;Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Testing" ToolsVersion="3.5"&gt;
    /// 
    ///  &lt;!-- Do not edit this --&gt;
    ///  &lt;Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" /&gt;
    ///  &lt;UsingTask AssemblyFile="C:\Base\Junk\UpdateMetadata\UpdateMetadata\bin\Debug\UpdateMetadata.dll" TaskName="UpdateMetadata"/&gt;
    /// 
    /// 
    ///  &lt;!--Re-setup the solutions to build definition--&gt;
    ///  &lt;ItemGroup&gt;
    ///    &lt;SolutionToBuild Include="$(BuildProjectFolderPath)\ChangeThisOne.sln"&gt;
    ///      &lt;Properties&gt;Change&lt;/Properties&gt;
    ///    &lt;/SolutionToBuild&gt;
    ///    &lt;SolutionToBuild Include="$(BuildProjectFolderPath)\ChangeThisToo.sln"&gt;
    ///      &lt;Properties&gt;Change&lt;/Properties&gt;
    ///    &lt;/SolutionToBuild&gt;
    ///    &lt;SolutionToBuild Include="$(BuildProjectFolderPath)\DontChangeThisOne.sln"&gt;
    ///      &lt;Properties&gt;Don'tChange&lt;/Properties&gt;
    ///    &lt;/SolutionToBuild&gt;
    ///  &lt;/ItemGroup&gt;
    /// 
    ///  &lt;Target Name="Testing"&gt;
    ///    &lt;Message Text="Before = %(SolutionToBuild.Identity) %(SolutionToBuild.Properties)" /&gt;
    /// 
    ///    &lt;ItemGroup&gt;
    ///      &lt;ItemsToChange Include="@(SolutionToBuild)"&gt;
    ///        &lt;Properties&gt;ChangedValue&lt;/Properties&gt;
    ///      &lt;/ItemsToChange&gt;
    ///   
    ///      &lt;ItemsToChange Remove="%(ItemsToChange.rootdir)%(ItemsToChange.directory)DontChangeThisOne%(ItemsToChange.extension)"/&gt;      
    ///    &lt;/ItemGroup&gt;
    /// 
    ///    &lt;ItemGroup&gt;
    ///      &lt;MetaDataToChange Include="Properties"/&gt;
    ///    &lt;/ItemGroup&gt;
    /// 
    ///    &lt;UpdateMetadata SourceList="@(SolutionToBuild)" ItemsToModify="@(ItemsToChange)" MetadataToModify="@(MetaDataToChange)"&gt;
    ///      &lt;Output TaskParameter="NewList" ItemName="SolutionToBuildTemp" /&gt;
    ///    &lt;/UpdateMetadata&gt;
    /// 
    ///    &lt;ItemGroup&gt;
    ///      &lt;SolutionToBuild Remove="@(SolutionToBuild)"/&gt;
    ///      &lt;SolutionToBuild Include ="@(SolutionToBuildTemp)"/&gt;
    ///    &lt;/ItemGroup&gt;
    ///         
    ///    &lt;Message Text="After  = %(SolutionToBuild.Identity) %(SolutionToBuild.Properties)"/&gt;
    ///  &lt;/Target&gt;
    ///&lt;/Project&gt;
    ///</summary>
    public class UpdateMetadata : Task
    {
        ///<summary>
        /// The list to modify.
        ///</summary>
        [Required]
        public ITaskItem[] SourceList { get; set; }

        ///<summary>
        /// Items in <see cref="SourceList"/> to change the Metadata for.  
        /// It should have the valid metadata set.
        ///</summary>
        [Required]
        public ITaskItem[] ItemsToModify { get; set; }


        ///<summary>
        /// List of metadata to modify.  This is an item group, but any metadata in it is ignored.
        ///</summary>
        public ITaskItem[] MetadataToModify { get; set; }

        ///<summary>
        /// If true then info about the update is output
        ///</summary>
        public Boolean OutputMessages { get; set; }

        ///<summary>
        /// Changed List.  If you call the following it can replace the <see cref="SourceList"/>:
        ///</summary>
        [Output]
        public ITaskItem[] NewList { get; set; }

        ///<summary>
        /// Runs the task to output the updated version of the property
        ///</summary>
        ///<returns></returns>
        public override bool Execute()
        {
            // If we got empty params then we are done.
            if ((SourceList == null) || (ItemsToModify == null) || (MetadataToModify == null))
            {
                Log.LogMessage("One of the inputs to ModifyMetadata is Null!!!", null);
                return false;
            }
            if (OutputMessages)
                Log.LogMessage(MessageImportance.Low, "Beginning Metadata Changeover", null);
            int sourceIndex = 0;
            foreach (ITaskItem sourceItem in SourceList)
            {
                // Fill the new list with the source one
                NewList = SourceList;
                foreach (ITaskItem itemToModify in ItemsToModify)
                {
                    // See if this is a match.  If it is then change the metadat in the new list
                    if (sourceItem.ToString() == itemToModify.ToString())
                    {
                        foreach (ITaskItem metadataToModify in MetadataToModify)
                        {
                            try
                            {

                                if (OutputMessages)
                                    Log.LogMessage(MessageImportance.Low, "Changing {0}.{1}",
                                        NewList[sourceIndex].ToString(), metadataToModify.ToString());
                                // Try to change the metadata in the new list.
                                NewList[sourceIndex].SetMetadata(metadataToModify.ToString(),
                                                                 itemToModify.GetMetadata(metadataToModify.ToString()));

                            }
                            catch (System.ArgumentException exception)
                            {
                                // We got some bad metadata (like a ":" or something).
                                Log.LogErrorFromException(exception);
                                return false;
                            }
                        }
                    }
                }
                sourceIndex += 1;
            }

            return true;
        }
    }
}

我希望这对某些人有用,但是代码显然是“自担风险使用”。

瓦卡诺

票数 2
EN

Stack Overflow用户

发布于 2009-05-13 10:28:16

是的,您可以在定义<ItemGroup>的元数据后对其进行、修改或添加(MSBuild 3.5)

代码语言:javascript
复制
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- Define ItemGroup -->
  <ItemGroup>
    <TestItemGroup Include="filename.txt">
      <MyMetaData>Test meta data</MyMetaData>
    </TestItemGroup>
    <TestItemGroup Include="filename2.txt">
      <MyMetaData>Untouched</MyMetaData>
    </TestItemGroup>
  </ItemGroup>

  <Target Name="ModifyTestItemGroup" BeforeTargets="Build">
    <!-- Show me-->
    <Message Text="PRE:  %(TestItemGroup.Identity)  MyMetaData:%(TestItemGroup.MyMetaData)  OtherMetaData:%(TestItemGroup.OtherMetaData)" Importance="high" />

    <!-- Now change it - can only do it inside a target -->
    <ItemGroup>
      <TestItemGroup Condition="'%(TestItemGroup.MyMetaData)'=='Test meta data' AND 'AnotherCondition'=='AnotherCondition'">
        <MyMetaData>Well adjusted</MyMetaData>
        <OtherMetaData>New meta data</OtherMetaData>
      </TestItemGroup>
    </ItemGroup>

    <!-- Show me the changes -->
    <Message Text="POST: %(TestItemGroup.Identity)  MyMetaData:%(TestItemGroup.MyMetaData)  OtherMetaData:%(TestItemGroup.OtherMetaData)" Importance="high" />
  </Target>

  <Target Name="Build" />
</Project>

参考:MSDN Library: New Methods for Manipulating Items and Properties (MSBuild)

票数 42
EN

Stack Overflow用户

发布于 2019-01-14 06:24:26

有一种通过使用Update属性修改元数据的新方法,例如。

代码语言:javascript
复制
<ItemGroup>
    <Compile Update="somefile.cs">  // or Update="*.designer.cs"
        <MetadataKey>MetadataValue</MetadataKey>
    </Compile>
</ItemGroup>  

MSBuild documentation中有更多信息

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/841913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档