2010-09-11 5 views
13

Ich versuche, einen Ordner rekursiv zu mehrere Zielordner mit MSBuild Kopieren kopieren Aufgabe zu kopieren. Ich habe die folgende Frage gesehen, die mir einen guten Start gab, aber ich muß etwas fehlen:Wie kann ich den MSBuild-Kopiervorgang zum Kopieren in mehrere Zielordner verwenden?

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

Ein Ausschnitt aus meiner Build-Datei unten:

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

Als ich das laufen , die „Message“ Aufgabe, wie ich erwarten würde, spuckt 2 Zeilen:

\\server1\path 
\\server2\path 

das Problem ist, erscheint das „Kopieren“ Task nur einmal ausführen, und kopiert die Dateien in das Stammverzeichnis der Strom-Festplatte und nicht die angegebenen Netzwerkpfade:

Kopien zu C:\file1.txt statt \\server1\path\file1.txt

Ich bin zu MSBuild ziemlich neu, so fühle ich mich wie ich etwas ziemlich einfach hier bin fehlt.

Jede Hilfe würde sehr geschätzt werden.

Antwort

22

Was Sie hier zu tun haben, ist als Batching bekannt. Ich habe ziemlich viel über Batching gebloggt. Sie können meine Blogs unter http://sedotech.com/Resources#Batching aufgelistet finden. Batching ist eine Möglichkeit, eine Schleife auszuführen, ohne wirklich eine in MSBuild auszuführen. Sie können Gruppen in Werte mit einem gemeinsamen Metadatenwert aufteilen. Metadaten können Werte wie Identität, FullPath, Dateiname usw. sein. Sie können sogar eigene Metadaten erstellen. In jedem Fall, wenn Sie mehr als einen Wert aufteilen, werden sie unabhängig voneinander gestapelt. Sieh dir das Beispiel an, das ich erstellt habe. Das Ergebnis der Ausführung des Ziels wird nach dem Skript angezeigt.

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

Ausgabe

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

Ausgezeichnete Erklärung und Beispiel. Vielen Dank! – WayneC

+0

Ich könnte mich selbst treten - hatte diese Lösung vor Stunden geöffnet aber kämpfte darum, das Kopieren zu mehreren Zielen zu bekommen - der 3. Ansatz hat es geschafft! – Oliver

3

Das wichtigste fehlende Stück im Puzzle, ohne die das Outputs Attribut auf das Target Element zu sein scheint, werden Sie immer nur das Ziel für ein Element des Execute ganze Liste. Das andere Teil ist die neue Eigenschaft, die Sie auf dem Weg definieren müssen.

Die Lösung für Ihr Problem würde wie folgt aussehen:

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