MSbuild复制整个文件夹

时间:2011-02-25 23:01:47

标签: .net visual-studio msbuild

尝试复制整个文件夹,但是当我这样做时:

<Copy SourceFiles="$(TargetDir)\*.*" DestinationFolder="$(BuildOutput)\SomeDir" />

副本尝试执行此操作:复制c:\ source \ *。* c:\ destination \ SomeDir \ *。* 并失败并显示“非法字符”

7 个答案:

答案 0 :(得分:57)

明确指定SourceFiles的ItemGroup。

<ItemGroup>
    <_CopyItems Include="$(TargetDir)\*.*" />
</ItemGroup>
<Copy
    SourceFiles="@(_CopyItems)"
    DestinationFolder="$(BuildOutput)\SomeDir"
    />

请注意_CopyItems是一种项目类型,因此使用“@”符号而不是“$”引用它。

答案 1 :(得分:24)

可以使用以下代码片段来复制文件,该代码片段可处理防病毒程序和子目录

  <ItemGroup>
        <SomeAppStuff Include="$(SolutionDir)\ProjectXXX\bins\**\*.*" />
  </ItemGroup>
  <Copy 
      SourceFiles="@(SomeAppStaff)" 
      DestinationFolder="$(OutputPath)\%(RecursiveDir)" 
      SkipUnchangedFiles="true"
      OverwriteReadOnlyFiles="true" 
      Retries="3"
      RetryDelayMilliseconds="300"/>

指定$(OutputPath)\%(RecursiveDir)会要求复制任务尊重子文件夹,因此它会将源目录的子文件夹放在目标目录的子文件夹中。

SkipUnchangedFiles将提高具有足够内存的计算机的构建速度,因为当RAM足够时,Windows会优化常用文件的IO。

RetriesRetryDelayMilliseconds处理相关问题 a)压缩的NTFS文件系统,在很少情况下构建失败时b)带有SSD驱动器的防病毒软件。

答案 2 :(得分:14)

查看MSDN文档,我相信SourceFiles参数需要ITaskItem []值。见MSDN MSBuild Copy Task

上述链接的最后一个示例是从一个目录到另一个目录进行递归复制,维护文件夹结构。

答案 3 :(得分:6)

如果您将文件夹放在c#项目的根目录中,那么您可以将其简单地放入csproj中。

<ItemGroup>
    <None Update="FolderToCopy\**\*.*">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
</ItemGroup>

我只测试了2017版csproj,但我认为它向后兼容。虽然可能是错的

答案 4 :(得分:2)

成功完成此任务

<Target Name="AfterBuild">
  <ItemGroup>
    <SomeDir Include="$(SolutionDir)\SomeOtherProject\SomeDir\**\*" />
  </ItemGroup>
  <Copy 
    SourceFiles="@(SomeDir)" 
    DestinationFiles="@(SomeDir->'$(OutDir)\SomeDir\%(RecursiveDir)%(Filename)%(Extension)')" 
    SkipUnchangedFiles="true" 
    OverwriteReadOnlyFiles="true" 
    Retries="3" 
    RetryDelayMilliseconds="300" />

答案 5 :(得分:0)

对我来说这是有效的: -保留文件夹结构 -复制了文件夹中的所有文件 -适用于任何文件夹,不必在项目或同一项目文件夹中

<ItemGroup>
    <_CopyItems Include="<path relative to project>\**\*.*" />
</ItemGroup>

<Target Name="AfterBuild">
  <Copy SourceFiles="@(_CopyItems)" DestinationFiles="@(_CopyItems->'$(OutDir)\<output folder>\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>

传奇:

  • <path relative to project>:这可以是任何路径,使用.. \表示 在proj文件夹上方工作
  • <output folder>:您想要的文件夹 要放入的整个文件结构,不包括源 文件夹。
  • $(OutDir)将是bin \ Debug或您具有的任何构建模式(如果需要) 否则,改变它。

答案 6 :(得分:0)

对我来说最好的解决方案是使用魔术XCOPY,因为我必须复制所有文件和子目录

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
  <PropertyGroup>
    <FilesSource>$(ProjectDir)\lib</FilesSource>
    <FilesDestination Condition=" '$(SolutionName)' == 'any name a' ">$(ProjectDir)\..\..\Something\lib</FilesDestination>
    <FilesDestination Condition=" '$(SolutionName)' == 'the top solution name' ">$(SolutionDir)\Something\lib</FilesDestination>
  </PropertyGroup>
  <Error Condition=" '$(FilesDestination)' == '' " Text="Lib not delivered. To disable this message, remove the 'Target' tag from the project file" />
  <Exec Command="RD /S /Q &quot;$(FilesDestination)&quot;" />
  <Exec Command="XCOPY &quot;$(FilesSource)&quot; &quot;$(FilesDestination)&quot; /E /I /H /R /K /Y" />
  <Exec Command="RD /S /Q &quot;$(FilesSource)&quot;" />
</Target>

一旦构建成功,就会触发此构建事件,它将清除FilesDestination文件夹,然后将所有具有目录结构的文件FilesSource复制到FilesDestination,然后删除FilesSource文件夹以使所有内容保持“ bien propre”:)

注意

对于FilesDestination,请确保使用条件属性或将其删除,以使复制过程结束