【问题标题】:MSBuild TargetOutputs doesn't include Foo.exe.config file?MSBuild TargetOutputs 不包含 Foo.exe.config 文件?
【发布时间】:2010-08-18 14:38:31
【问题描述】:

我正在使用MSBuild 任务如下:

<MSBuild Projects="Foo.csproj">
    <Output TaskParameter="TargetOutputs" ItemName="FilesToDeploy" />
</MSBuild>

但是FilesToDeploy项组只包含项目文件构建的.EXE文件;它不包括Foo.exe.config 文件。

另一个问题:Who copies App.config to App.exe.config? 解释了 MSBuild 如何准确找到/复制配置文件,但我不知道如何实际获取名称。

我发现了一个类似的问题elsewhere,但没有答案。

我该如何解决这个问题?

【问题讨论】:

标签: msbuild


【解决方案1】:

让我解释一下这里发生了什么。我将不得不假设您在这里构建的子项目是未经修改的 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,我不想在这里发布并搞砸这个答案

【讨论】:

  • 太棒了!如果 $(Csproj) 实际上是 $(Csprojs),我将如何更改它?那就是:如果我想处理多个项目,我需要对 PrimaryOutputTargetDir 的东西做些什么?还是有更好的方法来做到这一点?
  • 另外:App.config -> Foo.exe.config 转换似乎在某种程度上很神奇。据我所知,您提出的解决方案没有解决这个问题。有什么想法吗?
  • 啊 - 这有点诡计......你需要一个调用目标,它会在你的源项目列表上执行相当于“foreach”的操作,为列表中的每个项目调用这个目标。在这个答案中查看我的批处理技术:stackoverflow.com/questions/3459043/…
  • 好的。我得到了批处理(foreach)的工作。我将 Inputs="@(ProjectsToPublish)" Outputs="%(Identity).Dummy" 添加到我的目标中。我仍在寻找包含 Foo.exe.config 的方法。
  • 我撤回了之前的回答并更新了文字。抱歉,无法提供更多帮助。
猜你喜欢
  • 2012-10-02
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多