代码之家  ›  专栏  ›  技术社区  ›  WayneC

如何使用MSBuild复制任务复制到多个目标文件夹?

  •  14
  • WayneC  · 技术社区  · 14 年前

    我正在尝试将文件夹递归复制到 倍数 使用MSBuild的复制任务的目标文件夹。我看到下面的问题给了我一个很好的开始,但我肯定错过了什么:

    Msbuild copy to several locations based on list of destination parameter?

    下面是我的生成文件中的一个片段:

    <ItemGroup>
        <DeployPath Include="\\server1\path" />
        <DeployPath Include="\\server2\path" />
    </Item Group>
    
    <Target Name="Deploy">
        <Message Text="%(DeployPath.Identity)" />
        <Copy SourceFiles="@(ItemsToCopy)" DestinationFolder="%(DeployPath.Identity)\%(RecursiveDir)" />
    </Target>
    

    当我运行此命令时,正如我所料,“Message”任务会弹出两行代码:

    \\server1\path
    \\server2\path
    

    复制到 C:\file1.txt \\server1\path\file1.txt

    我对MSBuild还比较陌生,所以我觉得这里缺少一些基本的东西。

    任何帮助都将不胜感激。

    2 回复  |  直到 7 年前
        1
  •  26
  •   Sayed Ibrahim Hashimi    14 年前

    您在这里处理的是批处理。我在博客上写了很多关于批处理的东西。你可以在以下网址找到我的博客 http://sedotech.com/Resources#Batching . 批处理是一种在MSBuild中执行循环而不真正执行循环的方法。可以将组拆分为具有公共元数据值的值。元数据可以是Identity、FullPath、Filename等值。您甚至可以创建自己的元数据。在任何情况下,当你批量处理超过一个值时,它们是相互独立的批处理。看看我创建的示例。执行目标的结果显示在脚本之后。

    <Project ToolsVersion="4.0" DefaultTargets="Demo" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      <ItemGroup>
        <ItemsToCopy Include="src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt"/>
      </ItemGroup>
    
      <ItemGroup>
        <DeployPath Include="C:\temp\path01\" />
        <DeployPath Include="C:\temp\path02\" />
      </ItemGroup>
    
      <!--
        Target batching is happening here because there is a 
        %() expression inside the Outputs attribute. So that 
        means that this target will be repeated once per
        uinque batch of %(DeployPath.Identity). Identity is
        the value that is passed in the Incude= attribute.
        Since we know there are two values we know that
        this target will be executed twice, and on each 
        pass the DeployPath item will only look to contain
        a single value. If there were duplicates then the list
        could contain more than 1 value.
      -->
      <Target Name="Demo" Outputs="%(DeployPath.Identity)">
        <Message Text="DeployPath.Identity: %(DeployPath.Identity)" />
    
        <Message Text="======================================" Importance="high"/>
        <Message Text="ItemsToCopy1: @(ItemsToCopy)|| DeployPath.Identity: %(DeployPath.Identity)" />
        <Message Text="======================================" Importance="high"/>
        <!--
          In the next emample you are batching on both the DeployPath item list as well as
          the ItemsToCopy item. When two batched items are in the same expression they are
          matched individually, so you ge a value for DeployPath metadata but not ItemsToCopy
          metadata. That is why your copy only copied to one location.
        -->
        <Message Text="ItemsToCopy2: @(ItemsToCopy)|| DeployPath.Identity-RecursiveDir: %(DeployPath.Identity)\%(RecursiveDir)" />
        <Message Text="======================================" Importance="high"/>
        <!-- 
          In this example I create a property and assign it the value of 
          %(DeployPath.Identity). We know there will only be one such
          value. Because there should only be one value with Identity 
          when this target is executed so it is safe to 
          convert item to property
    
          Because we are not batching on both items we will get the values for both vaules
          to be correct becuase the target is repeated for the other
          DeployPath values.
        -->
        <PropertyGroup>
          <_DeployPathIdentity>%(DeployPath.Identity)</_DeployPathIdentity>
        </PropertyGroup>
        <Message Text="ItemsToCopy3: @(ItemsToCopy)|| _DeployPathIdentity-RecursiveDir: $(_DeployPathIdentity)\%(RecursiveDir)" />
    
        <!-- 
          I've always preferred to use DestinationFiles so my sample
          below uses that. But you could change the target to use
          DestinationFolder instead.
        -->
        <Copy SourceFiles="@(ItemsToCopy)"
              DestinationFiles="@(ItemsToCopy->'$(_DeployPathIdentity)%(RecursiveDir)%(Filename)%(Extension)')" />
      </Target>
    
    </Project>
    

    输出

    Build started 9/10/2010 9:31:28 PM.
    Project "I:\Development\My Code\Community\MSBuild\CopyFiles01.proj" on node 1 (default targets).
    Demo:
      DeployPath.Identity: C:\temp\path01\
      ======================================
      ItemsToCopy1: src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt|| DeployPath.I
      dentity: C:\temp\path01\
      ======================================
      ItemsToCopy2: || DeployPath.Identity-RecursiveDir: C:\temp\path01\\
      ItemsToCopy2: src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt|| DeployPath.I
      dentity-RecursiveDir: \
      ======================================
      ItemsToCopy3: src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt|| _DeployPathI
      dentity-RecursiveDir: C:\temp\path01\\
      Creating directory "C:\temp\path01".
      Copying file from "src\0001.txt" to "C:\temp\path01\0001.txt".
      Copying file from "src\0002.txt" to "C:\temp\path01\0002.txt".
      Copying file from "src\sub\sub-0001.txt" to "C:\temp\path01\sub-0001.txt".
      Copying file from "src\sub\sub-0002.txt" to "C:\temp\path01\sub-0002.txt".
    Demo:
      DeployPath.Identity: C:\temp\path02\
      ======================================
      ItemsToCopy1: src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt|| DeployPath.I
      dentity: C:\temp\path02\
      ======================================
      ItemsToCopy2: || DeployPath.Identity-RecursiveDir: C:\temp\path02\\
      ItemsToCopy2: src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt|| DeployPath.I
      dentity-RecursiveDir: \
      ======================================
      ItemsToCopy3: src\0001.txt;src\0002.txt;src\sub\sub-0001.txt;src\sub\sub-0002.txt|| _DeployPathI
      dentity-RecursiveDir: C:\temp\path02\\
      Creating directory "C:\temp\path02".
      Copying file from "src\0001.txt" to "C:\temp\path02\0001.txt".
      Copying file from "src\0002.txt" to "C:\temp\path02\0002.txt".
      Copying file from "src\sub\sub-0001.txt" to "C:\temp\path02\sub-0001.txt".
      Copying file from "src\sub\sub-0002.txt" to "C:\temp\path02\sub-0002.txt".
    Done Building Project "I:\Development\My Code\Community\MSBuild\CopyFiles01.proj" (default targets
    ).
    
    
    Build succeeded.
    
        2
  •  5
  •   XDS    6 年前

    Outputs Target 元素,如果没有该元素,则始终只对整个列表中的一项执行目标。另一部分是您需要在途中定义的新属性。

    <ItemGroup>
        <DeployPath Include="\\server1\path" />
        <DeployPath Include="\\server2\path" />
    </ItemGroup>
    
    <Target Name="Deploy" Outputs="%(DeployPath.Identity)">
        <PropertyGroup>
            <Destination>%(DeployPath.Identity)</Destination>
        </PropertyGroup>
        <Message Text="Processing: '$(Destination)" />
        <Copy SourceFiles="@(ItemsToCopy)"
              DestinationFolder="%(DeployPath.Identity)\%(RecursiveDir)" />
    </Target>