1

Is there a way to get the CopyTask to copy the same file to multiple locations?

eg. I've generated an AssemblyInfo.cs file and want to copy it across to all my projects before building.

Gerrie Schenck
  • 22,148
  • 20
  • 68
  • 95
Veli Gebrev
  • 2,481
  • 4
  • 31
  • 48

3 Answers3

2

Check out the RoboCopy build task which is part of the Community Build Tasks library which you can find here. RoboCopy can copy one source file to multiple destinations.

On a side note: why don't you use one AssemblyInfo file on solution level and link to that in your projects if you need the same information in every project? Check out my accepted answer on this question: Automatic assembly version number management in VS2008

Community
  • 1
  • 1
Gerrie Schenck
  • 22,148
  • 20
  • 68
  • 95
  • Is the version packaged with the MSI on the community build tasks not the latest? Don't see the RoboCopy task after installing it... (It's not even in the documentation or sample project) – Veli Gebrev Jan 08 '10 at 09:52
  • hmm strange, it's in the list on the website though – Gerrie Schenck Jan 08 '10 at 10:00
2

Right, well maybe I should attempt to do the things I want to do before asking for help :)

    <ItemGroup>
        <AssemblyInfoSource 
            Include="AssemblyInfo.cs;AssemblyInfo.cs" />
        <AssemblyInfoDestination
            Include="$(Destination1)\AssemblyInfo.cs;$(Destination2)\AssemblyInfo.cs" />
    </ItemGroup>

    <Copy SourceFiles="@(AssemblyInfoSource)" DestinationFiles="@(AssemblyInfoDestination)" />
Veli Gebrev
  • 2,481
  • 4
  • 31
  • 48
  • Thanks for sharing. Does the number of source and destination files have to be the same? – Gerrie Schenck Jan 08 '10 at 10:12
  • Yeah, the number of files needs to match. I'm presuming you _can_ rename the destination files if needed though. http://msdn.microsoft.com/en-us/library/3e54c37h.aspx (Though I definitely think the linked AssemblyInfo option is the best thing to do here, thanks for that :) this is just for completeness) – Veli Gebrev Jan 08 '10 at 10:29
1

I had a need to copy the contents of a directory to multiple locations, this is what I came up with that works. So I am posting it here ins case anyone else is in similar need and comes across this question like I did.

<!-- Create a list of the objects in PublishURL so it will copy to multiple directories -->
<ItemGroup>
    <PublishUrls Include="$(PublishUrl)"/>
</ItemGroup>
<PropertyGroup>
   <Files>$(OutputPath)\**\*</Files>
</PropertyGroup>

<!-- CopyNewFiles will copy all the files in $(OutputPath) to all the directories in the
     in $(PublishUrl). $(PublishUrl) can be a single directory, or a list of directories
     separated by a semicolon     -->
<Target Name ="CopyNewFiles">

    <!-- Get list of all files in the output directory; Cross product this with all 
    the output directories. -->
    <CreateItem Include ="$(Files)"
        AdditionalMetadata="RootDirectory=%(PublishUrls.FullPath)">
      <Output ItemName ="OutputFiles" TaskParameter ="Include"/>
    </CreateItem>

    <Message Text="'@(OutputFiles)' -> '%(RootDirectory)\%(RecursiveDir)'"/>

    <Copy  SourceFiles="@(OutputFiles)"
           DestinationFolder ="%(RootDirectory)\%(RecursiveDir)"/>
</Target>

If you want to copy AssemblyInfo.cs to Folders A and B you would set the property Files="AssemblyInfo.cs" and PublishUrls="A;B"

What makes this work is the extra metadata in the CreateItem task AdditionalMetadata="RootDirectory=%(PublishUrls.FullPath)" so for each files found in File it creates 1 entry for each item found in PublishUrls. In your case of a single file the equivelent in writing out the xml would be:

<ItemGroup>
    <OutputFiles Include="AssemblyInfo.cs">
        <RootDirectory>A</RootDirectory>
    </OutputFiles>
    <OutputFiles Include="AssemblyInfo.cs">
        <RootDirectory>B</RootDirectory>
    </OutputFiles>
</ItemGroup>

Now if you copied the contents of a folder that had files 1.txt and 2.txt copied to A and B the equivalent xml would be:

<ItemGroup>
    <OutputFiles Include="1.txt">
        <RootDirectory>A</RootDirectory>
    </OutputFiles>
    <OutputFiles Include="2.txt">
        <RootDirectory>A</RootDirectory>
    </OutputFiles>
    <OutputFiles Include="1.txt">
        <RootDirectory>B</RootDirectory>
    </OutputFiles>
    <OutputFiles Include="2.txt">
        <RootDirectory>B</RootDirectory>
    </OutputFiles>
</ItemGroup>
Apeiron
  • 694
  • 7
  • 13