16

我有以下一段 msbuild 代码:

  <PropertyGroup>
    <DirA>C:\DirA\</DirA>
    <DirB>C:\DirB\</DirB>
  </PropertyGroup>

  <Target Name="CopyToDirA"
          Condition="Exists('$(DirA)') AND '@(FilesToCopy)' != ''"
          Inputs="@(FilesToCopy)"
          Outputs="@(FilesToCopy -> '$(DirA)%(Filename)%(Extension)')">
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DirA)" />
  </Target>

  <Target Name="CopyToDirB"
          Condition="Exists('$(DirB)') AND '@(FilesToCopy)' != ''"
          Inputs="@(FilesToCopy)"
          Outputs="@(FilesToCopy -> '$(DirB)%(Filename)%(Extension)')">
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DirB)" />
  </Target>

  <Target Name="CopyFiles" DependsOnTargets="CopyToDirA;CopyToDirB"/>

因此,调用目标CopyFiles会将相关文件复制到$(DirA)and $(DirB),前提是它们尚未存在且不是最新的。

但目标CopyToDirACopyToDirB外观相同,除了一个复制到$(DirA)和另一个复制到$(DirB)。是否可以将它们统一为一个目标,首先调用 with $(DirA),然后调用 with $(DirB)

谢谢。

4

3 回答 3

14

您应该能够生成一个 ItemGroup 包含 Dirs 然后 % 。

<ItemGroup>
    <Dirs Include="C:\DirA\;C:\DirB\">
</ItemGroup>
<Target Name="CopyFiles"
    Condition="Exists('%(Dirs)') AND '@(FilesToCopy)' != ''"
    Inputs="@(FilesToCopy)"
    Outputs="@(FilesToCopy -> '%(Dirs)%(Filename)%(Extension)')">
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="%(Dirs)" />
</Target>

或者您可以进行 2 次显式调用:

<Target Name="CopyFiles">
    <MsBuild Projects="$(MSBuildProjectFullPath)" Targets="CopyASetOfFiles" Properties="FilesToCopy=@(FilesToCopy);DestDir=$(DirA)" />
    <MsBuild Projects="$(MSBuildProjectFullPath)" Targets="CopyASetOfFiles" Properties="FilesToCopy=@(FilesToCopy);DestDir=$(DirB)" />
</Target>

<Target Name="CopyASetOfFiles"
    Condition="Exists('$(DestDir)') AND '@(FilesToCopy)' != ''"
    Inputs="@(FilesToCopy)"
    Outputs="@(FilesToCopy -> '$(DestDir)%(Filename)%(Extension)')">
    <Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DestDir)" />
</Target>

我没有测试过这两种语法,但对第二种语法相对更有信心。

(答案,如果有的话,在我桌子上的 Sayed Hashimi 书中——你必须等到第一个:

  1. 拿到书
  2. 我觉得无聊
  3. 赛义德找到了这篇文章并提出了一个经过测试的绝妙答案)
于 2009-08-18T15:35:09.630 回答
9

正如有人已经提到的那样,答案是批处理。

以下是一些链接:

于 2009-08-20T05:07:51.140 回答
4

是的,您想要的是 MSBuild 中的批处理。这

;%(Dirs.Identity)

在 Outputs 中定义将导致为 Dirs ItemGroup 中的每个项目执行此任务。

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="CopyFiles"
   xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   ToolsVersion="3.5">

<ItemGroup>
    <Dirs Include="C:\DirA" />
    <Dirs Include="C:\DirB" />
</ItemGroup>

<Target Name="CopyFiles"
    Inputs="@(FilesToCopy);@(Dirs)"
    Outputs="@(FilesToCopy -> '%(Dirs.Identity)%(Filename)%(Extension)');%(Dirs.Identity)" >
    <Message Text="%(Dirs.Identity)" />
</Target>

</Project>

输出:

Build started 8/19/2009 10:11:57 PM.
Project "D:\temp\test.proj" on node 0 (default targets).
  C:\DirA
CopyFiles:
  C:\DirB
Done Building Project "D:\temp\test.proj" (default targets).

将 Message 任务更改为具有以下条件的 Copy 任务,您就完成了:

Condition="Exists('%(Dirs.Identity)') AND '@(FilesToCopy)' != ''"
于 2009-08-20T02:20:15.630 回答