MsBuild和MsDeploy在多个环境中的应用

33

如何将解决方案配置映射到环境并使用MsDeploy为每个环境打包?

最简版本:下载此文件,并尝试更改.msbuild文件以创建一个包。


细节

我有一个包含大量库和ASP.NET MVC应用程序的解决方案。我使用msbuild文件驱动构建,该文件调用主要解决方案,然后执行其他操作。我想使用新的msdeploy打包功能来准备.zip文件以供稍后分发,但我遇到了各种困难。

我的解决方案有4个配置:Local、Dev、Test和Prod,与我想要映射的环境相匹配。在该解决方案中,所有库都像通常一样具有Debug和Release模式。例如,在Local解决方案模式下,所有库都以Debug模式编译。然后,主应用程序与解决方案具有匹配的环境,这样我就可以拥有Web.Dev.config等相应的文件,这似乎是使用这些东西的自然方法。

如果我按照以下方式打包:

<Target Name="BuildWebPackage">
  <MSBuild Projects="..\Publisher\Site\Site.vbproj"
           Targets="Package"/>
</Target>

我遇到了一个问题,就是Configuration=Local错误地映射到了Site.vbproj引用的库项目中,导致无法编译它们。


我看到两种可能的解决方案:其中一种我无法正确执行,另一种则非常丑陋。

尝试1

我尝试通过解决方案调用Package目标(在本例中,“Applications”是包含Site项目的解决方案文件夹...我为了简化这篇文章,实际上解决方案中有多个应用程序)。

<Target Name="BuildWebPackage">
  <MSBuild Projects="..\Publisher\Publisher.sln"
           Targets="Applications\Site:Package"/>
</Target>

我认为这种 SolutionFolder\ProjectName:Target 语法是实现此操作的方法,因为 :Clean 可以运行... 但是,这会引发

error MSB4057: The target "Applications\Site:Package" does not exist in the project.

尝试2

现在是一个丑陋的解决方案:如果我修改我的所有库以拥有这4个解决方案配置的4个额外配置,则可以解决问题。然而,如果我想以后与具有不同环境的项目共同开发共享库,则这很丑陋且确实是一个糟糕的计划。此外,那些环境与库无关,仅在使用库的顶级应用程序的上下文中才有意义。味道不好。


啥?

我喜欢在解决方案中拥有多个环境和花哨的新Web.config替换功能,但我不知道如何在这种情况下调用msdeploy的Package任务,以便我可以在TeamCity中构建软件包。

(请注意,我可能不想调用msdeploy命令行,因为它用于将IIS应用程序转换为软件包。这不是我在这里做的事情。)


示例

再次,我完全被难住了,因此如果您想进行实验并提供帮助,我已经准备好了此示例解决方案


如果有人能指出与所讨论的Package任务有关的任何文档,那将会很有帮助,因为在谷歌搜索“msdeploy package task”时,这已经排名第二了,但我在微软官网上找不到任何相关信息。 - Dan Fitch
我对你在这里尝试的内容有点困惑。所以,当你在 Visual Studio 之外调用构建时,“问题”就会出现?(如果是这样,那么这对我来说就更有意义了) - Taylor Bird
是的,正确的。我想在 CI 环境中运行构建。 - Dan Fitch
2个回答

40

第一次尝试失败是因为解决方案文件中不存在Package目标。使用MSBuild处理解决方案文件时,会创建一个临时的MSBuild项目文件(SamplePackage.sln.metaproj);这个项目文件只包含一些目标(Build, Clean, Rebuild, Publish, ...)。

解决方案:使用DeployOnBuild & DeployTarget属性

实现您所需的一种方法是使用DeployOnBuild属性,像这样:

<PropertyGroup Condition="'$(Configuration)' == ''">
  <Platform>Any Cpu</Platform>
  <Configuration>Dev</Configuration>
  <PackageLocation>$(MSBuildProjectDirectory)\package.zip</PackageLocation>
</PropertyGroup>

<Target Name="Build">
  <MSBuild Projects="SamplePackage.sln"
           Targets="Build"/>
</Target>

<Target Name="BuildWebPackage">
  <MSBuild Projects="SamplePackage.sln"
           Properties="Platform=$(Platform);
                       Configuration=$(Configuration);
                       DeployOnBuild=true;
                       DeployTarget=Package;
                       PackageLocation=$(PackageLocation);"/>
</Target>
  • DeployOnBuild=true: 在调用“Build”时,必须进行部署。
  • DeployTarget=Package: 用于部署创建一个包。
  • PackageLocation: 指示包文件的文件路径。

附加链接:


花在这上面的时间...这确实没有在任何地方得到很好的记录。我向你致敬,先生。 - Ryan Eastabrook

0

我做过类似的事情,可能会有用。在最近的一个项目中,我们有“Dev”、“Test”和“Prod”环境。

我为每个环境添加了解决方案配置,例如:

  • Release-Dev
  • Release-Test
  • Release-Prod

对于大多数解决方案中的项目,这些配置只是链接到常规的“Release”构建,但在适当的情况下,一些项目确实具有不同的“Release-Test”构建配置,其中代码中可能会有#if/#endif的内容。

这也有助于允许根据每个配置自定义您的msdeploy配置。

关于msbuild目标。该目标引用元素的名称。例如,您可以使用/t:BuildWebPackage调用msbuild以获取上面的示例。


是的,目标是指一个元素。我的问题不在于调用BuildWebPackage,而是在于在BuildWebPackage中调用什么才能正确地使用新的打包好处来构建包。在您的示例中,如果我使Web项目具有“Release-Test”,那么我可以在该.proj文件上调用package,但然后msbuild尝试构建所有其他库也在“Release-Test”中。如果我尝试构建sln,则不知道要放入哪个msdeploy目标,因为“Package”在解决方案级别上不再可用。 - Dan Fitch
嗯...所以如果您确实想要构建依赖项,那么这似乎是一个合理的事情。否则,您是否可以在解决方案配置管理器中取消选中那些项目的“构建”选项?也许我误解了您的问题。 - David Gardiner
问题在于解决方案知道要在“Release”中查找库文件,但proj文件认为它应该在“Release-Test”中查找这些库文件,但实际上这个目录并不存在,因此它尝试构建这些库文件,但却失败了。我将打包一个简单的示例项目并将其放在某个地方。 - Dan Fitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接