Modify MSBuild ItemGroup Metadata

前端 未结 6 468
渐次进展
渐次进展 2020-12-09 08:46

Is it possible to modify a ItemGroup\'s metadata after it is declared.

For Example:

  
    

        
6条回答
  •  -上瘾入骨i
    2020-12-09 09:12

    I had to write a custom task to do this:

    Here is how it works

    
      
        ChangedValue
      
      
    
    
    
      
    
    
    
      
      
    
    

    It fills a new item called SolutionToBuildTemp with the changed value. I then remove everything in the SolutionToBuild item and fill it iwith the SolutionToBuildTemp item.

    Here is the code for the task if anyone is interested (I did submit it to the MSBuildExtenstionPack too).

    // 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
    {
        ///
        /// Used to update the metadata in a ItemGroup (Note: Requires an MSBuild Call After using this task to complete the update.  See Usage.)
        /// Usage:
        /// <?xml version="1.0" encoding="utf-8"?>
        ///<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Testing" ToolsVersion="3.5">
        /// 
        ///  <!-- Do not edit this -->
        ///  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
        ///  <UsingTask AssemblyFile="C:\Base\Junk\UpdateMetadata\UpdateMetadata\bin\Debug\UpdateMetadata.dll" TaskName="UpdateMetadata"/>
        /// 
        /// 
        ///  <!--Re-setup the solutions to build definition-->
        ///  <ItemGroup>
        ///    <SolutionToBuild Include="$(BuildProjectFolderPath)\ChangeThisOne.sln">
        ///      <Properties>Change</Properties>
        ///    </SolutionToBuild>
        ///    <SolutionToBuild Include="$(BuildProjectFolderPath)\ChangeThisToo.sln">
        ///      <Properties>Change</Properties>
        ///    </SolutionToBuild>
        ///    <SolutionToBuild Include="$(BuildProjectFolderPath)\DontChangeThisOne.sln">
        ///      <Properties>Don'tChange</Properties>
        ///    </SolutionToBuild>
        ///  </ItemGroup>
        /// 
        ///  <Target Name="Testing">
        ///    <Message Text="Before = %(SolutionToBuild.Identity) %(SolutionToBuild.Properties)" />
        /// 
        ///    <ItemGroup>
        ///      <ItemsToChange Include="@(SolutionToBuild)">
        ///        <Properties>ChangedValue</Properties>
        ///      </ItemsToChange>
        ///   
        ///      <ItemsToChange Remove="%(ItemsToChange.rootdir)%(ItemsToChange.directory)DontChangeThisOne%(ItemsToChange.extension)"/>      
        ///    </ItemGroup>
        /// 
        ///    <ItemGroup>
        ///      <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>
        ///         
        ///    <Message Text="After  = %(SolutionToBuild.Identity) %(SolutionToBuild.Properties)"/>
        ///  </Target>
        ///</Project>
        ///
        public class UpdateMetadata : Task
        {
            ///
            /// The list to modify.
            ///
            [Required]
            public ITaskItem[] SourceList { get; set; }
    
            ///
            /// Items in  to change the Metadata for.  
            /// It should have the valid metadata set.
            ///
            [Required]
            public ITaskItem[] ItemsToModify { get; set; }
    
    
            ///
            /// List of metadata to modify.  This is an item group, but any metadata in it is ignored.
            ///
            public ITaskItem[] MetadataToModify { get; set; }
    
            ///
            /// If true then info about the update is output
            ///
            public Boolean OutputMessages { get; set; }
    
            ///
            /// Changed List.  If you call the following it can replace the :
            ///
            [Output]
            public ITaskItem[] NewList { get; set; }
    
            ///
            /// Runs the task to output the updated version of the property
            ///
            ///
            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;
            }
        }
    }
    

    I hope this is useful to some one, but the code is obviously "Use at your own risk".

    Vaccano

提交回复
热议问题