2008-11-05 137 views
7

我需要编写脚本。我使用MSBUILD是因为它与VS.net集成。我正在尝试从构建环境中将一些文件复制到部署文件夹。我正在使用MSBuild的复制任务。但不是像我所期望的那样复制目录树。它将所有内容复制到一个文件夹中。我将目录树中的所有文件重复放到一个文件夹中。我需要它将文件夹和目录树复制到目标文件夹中。有什么我失踪?MSBuild为什么不像我期望的那样复制

这里是我的构建脚本的初步认识部分:

<PropertyGroup> 
    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> 
    <Source>outputfolder</Source> 
    <DestEnv>x</DestEnv> 
    <DeployPath>\\networkpath\$(DestEnv)</DeployPath> 
</PropertyGroup> 
<ItemGroup> 
    <TargetDir Include="$(DeployPath)\**\*" Exclude="**\web.config"></TargetDir> 
    <SourceDir Include="$(Source)\**\*" /> 
</ItemGroup>  
<Target Name="Clean" > 
    <!-- clean detail ... --> 
</Target> 
<Target Name="migrate" DependsOnTargets="Clean"> 
    <Copy DestinationFolder="$(DeployPath)" SourceFiles="@(SourceDir)" /> 
</Target> 

回答

4

我发现例如在一个例子中MSDN我不明白,但会在计算器离开这里的一个例子我的同胞travlers 。下面是迁移目标从上面的固定版本:

<Target Name="migrate" DependsOnTargets="Clean"> 
    <Copy DestinationFiles="@(SourceDir->'$(DeployPath)\%(RecursiveDir)%(Filename)%(Extension)')" SourceFiles="@(SourceDir)" /> 
</Target> 

如果有人真的理解这个例子请解释。祝你好运!

12

当您为复制任务指定DestinationFolder时,它将从SourceFiles集合中获取所有项目并将它们复制到DestinationFolder。这是预料之中的,因为Copy任务无法确定每个项目的路径的哪部分需要用DestinationFolder替换以保持树结构。例如,如果您的SourceDir集合是这样定义的:

<ItemGroup> 
    <SourceDir Include="$(Source)\**\*" /> 
    <SourceDir Include="E:\ExternalDependencies\**\*" /> 
    <SourceDir Include="\\sharedlibraries\gdiplus\*.h" /> 
</ItemGroup> 

您认为目标文件夹树的外观如何?

要保存树,您需要进行标识转换并为SourceFiles集合中的每个项目生成一个目标项目。这里有一个例子:

<Copy SourceFiles="@(Compile)" DestinationFiles="@(Compile->'$(DropPath)%(Identity)')" /> 

副本任务将采取每个项目在SourceFiles集合,并通过在源项目规范与$(DropPath)前更换**部分转换其路径。

有人可能会争辩说,DestinationFolder属性应该已被写入作为快捷方式如下改造:

<Copy SourceFiles="@(Compile)" DestinationFiles="@(Compile->'$(DestinationFolder)%(Identity)')" /> 

唉,这将防止深复制到平面文件夹的场景,你正试图避免的,但其他人可能会在构建过程中使用。

5

很简单的例子,复制目录内容和结构递归:

<Copy SourceFiles="@(Compile)" DestinationFolder="c:\foocopy\%(Compile.RecursiveDir)"></Copy> 

@(编译)是要复制所有文件的的ItemGroup。可能是这样的:

<ItemGroup> 
     <Compile Include=".\**\*.dll" /> 
    </ItemGroup> 

复制任务将复制所有文件到c:\ foocopy就像xcopy。

+0

<复制SourceFiles = “$(SourceViewsLocation)” DestinationFolder = “$(RepositoryLocation)\%(RecursiveDir)”> 给出了错误:MSBUILD:错误MSB4095:该项目的元数据%(RecursiveDir)没有被引用项目名。使用%(itemname.RecursiveDir)指定项目名称。 – 2009-05-29 08:09:26

13

只是一个宝石,我们发现当我们周围复制调试MSBuild的问题:

http://blog.scrappydog.com/2008/06/subtle-msbuild-bug-feature.html

ItemGroups的目标之前解析,使创建新文件的任何目标(例如编译!)在沿着脚本进一步引用ItemGroup时不会被拾取。

埃里克·博文还介绍了一种绕过这个“功能”,该CreateItem任务:

<Target Name="Copy" > 
    <CreateItem Include="..\Source\**\bin\**\*.exe" 
     Exclude="..\Source\**\bin\**\*.vshost.exe"> 
     <Output TaskParameter="Include" ItemName="CompileOutput" /> 
    </CreateItem> 
    <Copy SourceFiles="@(CompileOutput)" 
     DestinationFolder="$(OutputDirectory)"></Copy> 
</Target> 

许多荣誉给他!

相关问题