una subcarpetas sobreescribir script por para otra mover copiar comando carpetas carpeta bat archivos msbuild msbuild-task

subcarpetas - ¿Cómo puedo usar la tarea de copia de MSBuild para copiar en varias carpetas de destino?



robocopy copiar carpetas y subcarpetas (2)

Intento copiar una carpeta de forma recursiva en varias carpetas de destino utilizando la tarea Copiar de MSBuild. He visto la siguiente pregunta que me dio un buen comienzo, pero me falta algo:

¿Copiar Msbuild a varias ubicaciones según la lista de parámetros de destino?

Un fragmento de mi archivo de compilación está 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 era de esperar, escupe 2 líneas:

//server1/path //server2/path

El problema es que la tarea "Copiar" parece ejecutarse solo una vez y copia los archivos en la raíz del disco duro actual y no en las rutas de red especificadas:

Copia en C:/file1.txt lugar de //server1/path/file1.txt

Soy bastante nuevo en MSBuild, así que me siento como si me estuviera perdiendo algo bastante básico aquí.

Cualquier ayuda sería muy apreciada.


La pieza faltante más importante en el rompecabezas parece ser el atributo Outputs en el elemento Target sin el cual siempre solo ejecutará 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 serí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>


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.