对 MSBuild ItemGroup 的内容感到困惑

Confused about contents of MSBuild ItemGroup

我正在开发一个 MSBuild 脚本,它的工作是构建一个解决方案,然后将两个项目的构建输出复制到一个统一的目录中。够简单了。

我正在使用 复制 任务执行此操作。像这样:

<ItemGroup>
    <OutputFiles1 Include="Project1\bin\Release\*.*" />
    <OutputFiles2 Include="Project2\bin\Release\*.*" />
</ItemGroup>

<Target CopyOutput>
    <Copy SourceFiles="@(OutputFiles1)" DestinationFolder="DeployOutput" />
    <Copy SourceFiles="@(OutputFiles2)" DestinationFolder="DeployOutput" />
</Target>

我遇到的问题是:当构建脚本 starts 时,两个 ItemGroup 元素包含目录的内容,当解决方案构建 完成 .

时,不是目录的内容

因此,例如,如果我在 Project1 中添加对新程序集的引用,然后 运行 生成,则 DeployOutput 目录不包含该新程序集,因为它不存在于项目输出中构建开始时的目录。但是如果我 运行 构建 再次 文件在那里并被复制。

似乎这种行为是设计使然,但我不确定如何在不生成批处理文件或类似文件来执行复制的情况下完成我的任务。

经典 msbuild evaluation order 问题:项目根中的项和属性基本上在解析时先于任何目标 运行 进行评估。但是,将它们放在目标中,并在目标 运行 时对它们进行评估。这对您的情况更好,因为您还可以确保一个目标 运行 接一个目标,从而使第一个目标看到后者产生的输出。插图:

<ItemGroup>
  <OutputFiles1 Include="Project1\bin\Release\*.*" />
</ItemGroup>

<Target Name="BuildIt">
  <Message Text="OutputFiles1=@(OutputFiles1 )" />
  <MSBuild Projects="Project1.vcxproj" Targets="Build" />
</Target>

<Target Name="Copy" DependsOnTargets="BuildIt">
  <ItemGroup>
    <ActualOutputFiles1 Include="Project1\bin\Release\*.*" />
  </ItemGroup>
  <Message Text="OutputFiles1=@(OutputFiles1)" />
  <Message Text="ActualOutputFiles1=@(ActualOutputFiles1 )" />
</Target>

当运行复制复制目标时(并且输出目录仍然是空的)你会得到类似

的输出
OutputFiles1=
.... build output ....
OutputFiles1=
ActualOutputFiles1=Project1\bin\Release\a.dll;......

OutputFiles1 始终为空,因为在评估时输出目录为空。然而,ActualOutputFiles1 在构建 之后 被评估,因此它包含输出目录的内容。