利用Powershell自动部署asp.net mvc网站项目 (一)

这一篇中咱们会写一些关于自动化部署的代码。咱们会使用 Powershell 书写这类代码。git

你将发现这篇文章中涉及的东西很是具体,有的要求甚至至关苛刻且可能不具备通用性。这是由于部署历来都是跟环境打交道,部署过程当中协做的组建太多,相互之间的交集不可能太大。可能惟一可以通用的是自动化部署的基本原则(只是这篇文章的基本原则):github

  • 每一次自动化部署结束以后,应用程序都会有相同的初始状态。
  • 自动化部署的机器很是干净,只有相应的 Windows Server 系统和 .NET Framework。尤为是,不会有 Visual Studio。

咱们须要公开一些基本的环境信息:shell

  • 64-bit Windows Server 2008/2012/2012 R2或者 64-bit Windows 7/8/8.1
  • 咱们的工程是使用 Microsoft Visual Studio 2013 开发的;
  • .NET Framework 版本为 4.5
  • ASP.NET MVC 的版本为 5.0.0
  • Microsoft Build Tool 的版本为 12.0

关于 MSBuild 这里须要多说几句。在 Visual Studio 2013 发布以前,MSBuild 是随 .NET Framework 一块儿发布的。这意味着咱们能够不用安装 Visual Studio 就能够构建 .NET 应用程序。服务器

这是多么美好的世界啊!所以,上一句话是假的。尤为是当你构建 ASP.NET Web 应用程序的时候,你立刻就会遇到 “Cannot found … WebApplication.target” 的错误。若是你 StackOverflow 一下就能够知道,咱们须要作的是安装 Visual Studio 或者从另一台安装了 Visual Studio 的机器上将相关的文件拷贝出来。这真是——丢人的设计!Linux 的拥趸又有了发泄的空间。编辑器

因而微软决定正视这个问题。从 Visual Studio 2013 开始,MSBuild 将与 Visual Studio 而不是.NET Framework 一块儿发布。这引来了一片骂声。我不得不说,你们在生活中不论遇到什么事情都要保持足够的冷静,每每先发脾气的得不到任何的好处。事实是,因为 .NET Framework 发布的周期是相对较长的,所以微软目前愈来愈倾向于使用 NuGet 进行类库的发布,这样有助于削减 .NET Framework 基础类库的大小,并缩短基础类库的发布周期。相应的 MSBuild 和 Visual Studio 的发布周期也但愿进行独立的变化。MSBuild 将和 Visual Studio 保持发布周期的一致性,并不意味这 MSBuild 依赖于 Visual Studio。所以咱们固然能够下载 MSBuild 的独立安装包 Microsoft Build Tools,并在一台没有 Visual Studio 的服务器上进行自动化构建。函数

再次强调,若是幸运,你能够直接运行这篇文章中的例子。可是你不要期望将这篇文章的脚本拷贝到你的工程就能够正常工做。由于部署是一个因地制宜的任务,须要具体分析。你可能会遇到各类各样的环境问题,可是我认为最重要的仍是思路。工具

部署是什么

简单来讲,部署就是 “构建(Build)” –> “拷贝” –> “配置”。那么咱们就开始一个一个解决它。这一篇将着眼于构建。ui

编译和构建应用程序 – 思路

如何构建应用程序呢?答案是先把须要的东西都拷贝过来,而后再用工具构建。好极了,咱们须要拷贝什么东西呢?固然是先把源代码拷贝过来。spa

┌────────────────┐ │ Src of MyApp │ └────────────────┘

光源代码还不行,由于咱们的程序依赖于第三方库(箭头表明依赖关系)。命令行

┌────────────────┐ │ Dependent libs │ └────────────────┘ ┌────────────────┐ │ Src of MyApp │ └────────────────┘

例如,对于咱们构建的那个简简单单的 ASP.NET MVC 5 的应用程序,咱们就须要在构建以前下载它依赖的类库:

  • Microsoft.AspNet.Mvc 5.0.0
  • Microsoft.AspNet.Razor 3.0.0
  • Microsoft.AspNet.WebPages 3.0.0
  • Microsoft.Web.Infrastructure 1.0.0.0

源代码和依赖库都拷贝完了,那么接下来咱们就须要将构建工具也拷贝过来:

┌────────────────┐ │ Dependent libs │ └────────────────┘ ┌────────────────┐ ┌───────────────────┐ │ Src of MyApp │────→│Tools for compiling│ └────────────────┘ └───────────────────┘

对于咱们来讲,构建的工具只有一个:

  • MSBuild

现在工具,源代码包罗万象,咱们能够开始编译了。

安装 MSBuild

若是你作实验的机器上安装了 Visual Studio 2013——Express 版本的也是能够的——那么你能够跳过这一步,不然请下载 Microsoft Build Tools 并安装。

下载应用程序的代码

咱们的代码是现成的,只须要从 git repository clone 下来就能够了。你也能够从这个地址 clone 到一个范例代码,并转换到相应的 commit。

git clone https://github.com/lxconan/MvcFromZero.git git reset --hard 340abb32433c99975bd6485f79db6ca077119477 

好了,完成了,到目前为止一切都是那么的轻松愉快。

下载应用的依赖库

咱们将使用 nuget 管理包的依赖。所以咱们首先要下载 NuGet 的命令行客户端,能够从这里下载。

接下来的行为都须要明确的目录结构。为了便于说明,咱们将创建以下的目录结构。

MvcFromZero  |- src  | |- FromZero.App  | |- packages  |  |- build  |- tools 

其中,src 目录存放 Solution 的源代码,而 build 目录存放自动化构建所需的各类工具和脚本。其中自动化构建须要的工具将放在 build/tools 目录下。所以咱们也会将 nuget.exe 放在这个目录下。

接下来咱们在 build 目录下创建 deploy.ps1 脚本,咱们将在这个脚本中完成接下来的任务。咱们先来下载依赖的包。NuGet 的包管理是经过 package.config 文件进行的。须要指出的是 package.config也具备必定的层次关系。首先 Solution 级别的包信息存储在两个地方:

  • 第一个是 Solution 目录下的 .nuget/package.config 文件,这个文件中存储的是非特定项目使用的包(若是并无这种类型的包,则该目录不存在,或者该目录下没有任何文件);
  • 第二个是 Solution 目录下的 packages/repositories.config 文件,这个文件存储了该解决方案下的每个工程的 packages.config 文件的路径。

而 Solution 下的每个 Project 的包定义存储在 Project 目录下的 package.config 中。

为了下载这些依赖的包是否须要人为遍历这些 config 文件呢?原来是,而从 nuget 2.7 开始,能够直接支持 Solution 范围内的包下载,因而额咱们就可使用以下的简单函数完成包的下载了。

Function Install-SolutionPackages() {  iex "$global_nugetPath restore $global_solutionFilePath" } 

其中,$global_nugetPath 是 nuget.exe 的路径,而 $global_solutionFilePath 是工程文件(在这里是 FromZero.App.csproj)的路径。

接下来须要肯定的是构建工具的位置,咱们可使用注册表查找 MSBuild 的位置的,因为咱们使用了 2013 版本的 MSBuild(Toolset 的版本号为 12.0),所以咱们的查找脚本为:

Function Get-MsBuildPath() {  $msBuildRegPath = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0"  $msBuildPathRegItem = Get-ItemProperty $msBuildRegPath -Name "MSBuildToolsPath"  $msBuildPath = $msBuildPathRegItem.MsBuildToolsPath + "msbuild.exe"  return $msBuildPath } 

上述两步完成以后,就能够编译咱们的工程了:

Function Compile-Project() {  iex -Command "& '$global_msBuildPath' $project_path" } 

你火烧眉毛的试验了你的代码,可是却发现出了问题,MSBuild 报告没法找到Microsoft.WebApplication.targets 文件。这是怎么回事,咱们已经明明在 MSBuild 中安装了Microsoft.WebApplication.targets 了啊?这是由于为了保持和 Microsoft Visual Studio 2010 SP1 的工程的兼容性,Visual Studio 2012/2013 的工程默认将 $(VisualStudioVersion) 环境变量设置为 10.0。这样,target 文件的查询路径就成了:

$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0 

而不是:

$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0 

所以咱们须要修正这个环境变量。请使用文本编辑器打开 FromZero.App.csproj 文件,找到以下的定义:

<PropertyGroup>  <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>  <VSToolsPath  Condition="'$(VSToolsPath)' == ''">  $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)  </VSToolsPath> </PropertyGroup> 

将其中的 VisualStudioVersion 节替换为:

<VisualStudioVersion>12.0</VisualStudioVersion> 

再次运行:祝贺你,你已经可以成功的下载全部的依赖,并完成工程的编译了!在本文的结束,附上 deploy.ps1 到目前为止的全部代码:

$ErrorActionPreference = 'Stop' # Environment helpers ------------------------------------ Function Get-MsBuildPath() {  $msBuildRegPath = "HKLM:\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0"  $msBuildPathRegItem = Get-ItemProperty $msBuildRegPath -Name "MSBuildToolsPath"  $msBuildPath = $msBuildPathRegItem.MsBuildToolsPath + "msbuild.exe"  return $msBuildPath } # Environment variables ---------------------------------- $global_buildDirPath = Get-Location $global_msBuildPath = Get-MsBuildPath $global_solutionPath = "$global_buildDirPath\..\src" $global_solutionFilePath = "$global_solutionPath\src.sln" $global_nugetPath = "$global_buildDirPath\tools\nuget.exe" # Install nuget packages --------------------------------- Function Install-SolutionPackages() {  iex "$global_nugetPath restore $global_solutionFilePath" } $project_path = $global_solutionPath + '\FromZero.App\FromZero.App.csproj' Function Compile-Project() {  iex -Command "& '$global_msBuildPath' '$project_path'" } Install-SolutionPackages Compile-Project
相关文章
相关标签/搜索