让我解释一下这里发生了什么。我将不得不假设您在这里构建的子项目是未经修改的 C-Sharp 项目。
默认情况下,.csproj 文件的默认目标为“Build”,因此当您在此处使用 MSBuild 任务时,它将执行项目中的默认目标。这被定义为
<Target
Name="Build"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(BuildDependsOn)"
Outputs="$(TargetPath)"/>
MSBuild 任务的文档表明“TargetOutputs”输出将包含在被调用目标的“输出”中声明的项目 - 在这种情况下,它是一个单个项目,即被调用项目中属性 $(TargetPath) 的值。此仅包含已构建的可执行文件或 DLL 的名称(请注意,不仅缺少 .config,还缺少任何引用的程序集!)
我正在撤回获得所有构建输出的原始解决方案,因为它不起作用 - 这是我在一个实用程序导入文件中的目标,但经过调查,我似乎并没有真正使用它任何地方,加上它要求您引用 Microsoft.CloudService.targets(我是,但怀疑你是)。
我认为您正在尝试做的是将构成 Foo.exe(包括 .config)的所有文件放入一个项目组中,以便您可以将它们复制到某处。这非常棘手,如果您考虑可以构成 csproj 输出的所有内容:主输出 (.exe)、配置文件、标记为 copyLocal 的引用程序集、附属程序集(您的 .resx DLL)、内容项等。
如果您知道在构建 csproj 文件时,它会将所有项目输出到一个 single 文件夹中,那么这一切都很容易处理。在 Visual Studio 中构建时确实如此,因为它将所有编译输出放入 bin\Debug。所以你会认为 FilesToDeploy 是$(OutDir)\**\*.*。但是,当您的项目由 TeamBuild 构建时,不是的情况 - 因为 TeamBuild 会将 OutDir 更改为一个全局“二进制”目录,每个项目输出到该目录(到防止重复构建等)。这意味着 FilesToDeploy 将包含该文件夹的内容,我怀疑这是您想要的。
您无疑已经发现了这一点(或至少预料到了这一点),这就是为什么您有一个目标询问 .csproj “您的构建输出是什么,它们在哪里?”。但是,您可以调用 Microsoft.Common.Targets 中没有单个 Target 来声明生成输出的整个 集。 Azure 小组试图解决这个问题(也许在他们试图做的事情的背景下成功了),我试图在我以前的解决方案中复制它,但它不起作用(或者至少,我没有时间让它工作)。
这并不全是理想的,但如果你重新审视我否决的假设,并不是所有的都丢失了:如果我们确实知道所有构建输出都将出现在一个文件夹中,那么问题将更容易解决。 VS 和 TeamBuild。然后 FilesToDeploy 将是一个简单的 ***.* glob。
如果您要修改 TfsBuild.Proj 并强制将项目的 OutDir 设置为(例如)$(BinariesRoot)\FooExe,则可以实现此目的:
<SolutionToBuild Include=$(SolutionRoot)\Sources\Foo.csproj">
<Properties>
OutDir=$(BinariesRoot)\FooExe\
</Properties>
</SolutionToBuild>
我实际上有一套完整的自定义“捆绑”目标 - 在 .csproj 文件中,我可以声明我希望输出的副本转到一组目录,并且目标会将所有输出复制到每个目录。但是,这只是我不得不介绍的东西,因为我在过去几个月中逐渐将旧版 nmake.exe 构建转换为原生 MSBuild,我不想在这里发布并搞砸这个答案