繁体   English   中英

MSBuild:复制整个文件夹

[英]MSBuild: copy whole folder

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

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

该副本尝试执行此操作:复制 c:\source\ c:\目的地\SomeDir\ 并因illegal characters错误而失败

明确指定 SourceFiles 的 ItemGroup。

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

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

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

  <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 文件系统,当构建在RetryDelayMilliseconds情况下失败 b) 带有 SSD 驱动器的防病毒软件。

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

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

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

查看 MSDN 文档,我相信 SourceFiles 参数需要 ITaskItem[] 值。 请参阅MSDN MSBuild 复制任务

上面链接的最后一个例子是从一个目录到另一个目录进行递归复制,保持文件夹结构。

成功完成了这样的任务

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

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

<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 或您拥有的任何构建模式,如果您想要其他东西,请更改它。

在 Visual Studio 15.4+ 中,有一个功能可以使这更容易——您可以设置LinkBaseLink来控制目标路径:

<ItemGroup>
  <Content Include="FolderToCopy\**" LinkBase="FolderInOutput\" CopyToOutputDirectory="Always" />
</ItemGroup>

来源: https://github.com/do.net/msbuild/issues/2949#issuecomment-362823310

对我来说最好的解决方案是使用神奇的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文件夹,然后将具有目录结构的所有文件FilesSourceFilesDestination ,然后删除FilesSource文件夹以保留所有内容“bien propre”:)

笔记

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM