2010-09-11 14 views
13

Estoy tratando de copiar una carpeta recursivamente a múltiples carpetas de destino usando la tarea Copiar de MSBuild. He visto a la siguiente pregunta, que me dio un buen comienzo, pero debo estar perdiendo algo:¿Cómo puedo usar la tarea de copia de MSBuild para copiar en varias carpetas de destino?

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

Un fragmento de mi fichero de construcción es a continuación:

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

Cuando ejecuto esto , la tarea "Mensaje", como me esperaba, escupe 2 líneas:

\\server1\path 
\\server2\path 

el problema es que la tarea "copia" aparece sólo una vez para funcionar, y copia los archivos en la raíz de la disco duro actual y no las rutas de red especificados:

copias a C:\file1.txt en lugar de \\server1\path\file1.txt

Soy bastante nuevo a MSBuild, así que me siento como que estoy perdiendo algo bastante básico aquí.

Cualquier ayuda sería muy apreciada.

Respuesta

22

Lo que está tratando aquí se conoce como procesamiento por lotes. He blogueado bastante sobre lotes. Puede encontrar mis blogs listados en http://sedotech.com/Resources#Batching. El procesamiento por lotes es una forma de hacer un ciclo sin realmente hacer uno en MSBuild. Puede dividir grupos en valores con un valor de metadato común. Los metadatos pueden ser valores como Identity, FullPath, Filename, etc. Incluso puedes crear tus propios metadatos. En cualquier caso, cuando haces un lote con más de 1 valor, se agrupan por lotes independientemente el uno del otro. Echa un vistazo al ejemplo que creé. El resultado de ejecutar el objetivo se muestra después del script.

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

salida

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

excelente explicación y ejemplo. ¡Gracias! – WayneC

+0

Podría patearme a mí mismo, si esta solución se hubiera abierto hace horas, pero hubiera seguido luchando para hacer que la copia funcionara en varios destinos, ¡el tercer enfoque lo hizo! – Oliver

3

La pieza que falta más importante en el rompecabezas parece ser el atributo Outputs en el elemento Target sin la cual usted siempre sólo se ejecuta el objetivo para un elemento de la lista completa La otra pieza es la nueva propiedad que necesita definir en el camino.

La solución a su problema se vería así:

<ItemGroup> 
    <DeployPath Include="\\server1\path" /> 
    <DeployPath Include="\\server2\path" /> 
</Item Group> 

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