[Powershell]使用Msbuild构建基于.NET Framework的WebAPI项目

  1. 查找最高版本的MsBuildTools。
  2. 清理缓存垃圾。
  3. 还原NuGet包。
  4. 构建解决方案。
  5. 按项目发布程序到本地。
  6. 按项目ZIP打包。
<#	
	.NOTES
	===========================================================================
	 Created with: 	Visual Studio 2019
	 Created on:   	2019/8/26 11:31
	 Created by:   	Allen
	 Organization: 	Allen
	 Filename:     	build_full.ps1
	===========================================================================
	.DESCRIPTION
		ERP devops scripts.
#>

# 声明全局变量
# 定义方法开始时输出的前景色
$LogForegroundColorStart = "Green"
# 定义方法结束时输出的前景色
$LogForegroundColorEnd = "Cyan"
# 定义方法输出警告时的前景色
$LogForegroundColorWarning = "DarkYellow"

Write-Host "`nPublish parameters initializing..." -Foreground $LogForegroundColorStart

# Set user level's parameters
# 定义当前脚本文件的绝对全路径
$CurrentScriptFilePath = $MyInvocation.MyCommand.Definition
# 定义当前脚本文件的所在的文件夹路径
$ScriptWorkPath = Split-Path -Parent $CurrentScriptFilePath
# 定义当前脚本文件的所在的解决方案文件夹路径
$SolutionPath = Split-Path -Parent $ScriptWorkPath
# 定义当前编译工作的文件夹路径
$BuildPath = "$SolutionPath\Builds"
# 定义要编译的解决方案名称
$SolutionName = "ERP"
# 定义要编译的解决方案文件名称
$SolutionFile = "$SolutionPath\$SolutionName.sln"
# 定义要发布的Web项目名称列表
$WebProjectNames = "API1", "API2", "API3"
# 定义要发布的Windows项目名称列表
$WinProjectNames = , "Job" # 只有一个元素的字符串数组,前面加 , 定义 表示
# 定义要打包的项目名称列表
$PackageNames = "API1", "API2", "API3", "Job"

# NuGet parameters
# 定义NuGet文件夹路径
$NuGetPath = "$SolutionPath\.nuget"
# 定义NuGet.exe文件路径
$NuGetExe = "$NuGetPath\NuGet.exe"
# 定义是否执行NuGet包还原: Y|N
$IfUseNuGetReStore = "Y" # value is Y or N
# 定义是否更新NuGet.exe主程序: Y|N
$IfUpdateNuGetTool = "N" # value is Y or N

# Set system level's parameters
# 定义编译时要使用的解决方案配置: Debug|Release
$Configuration = "Debug"
# 定义编译时要输出的日志等级: quiet|minimal|normal|detailed|diagnostic
$LogLevel = "normal"
# 定义要构建的.NET Framework版本
# Note: That the MSBuild tool version and VisualStudio version and the TargetFramework version have dependencies
$TargetFrameworkVersion = "4.5"
# 定义MsBuild.exe(Microsoft Build Tools)文件路径
$MSBuildExe = ""
# 定义MsBuild.exe(Microsoft Build Tools)版本
$MsBuildToolsVersion = ""

# 从高往低版本逐个找,优先使用最高版本的Microsoft Build Tools
Function Set-Msbuild-Tools
{
	# Visual Studio 2017 以上版本独立安装的 Build Tools
	if (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\*\BuildTools\MSBuild\*\Bin\MSBuild.exe")
	{
		if (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe"
			$script:MsBuildToolsVersion = "Current"
		}
		elseif (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe"
			$script:MsBuildToolsVersion = "15.0"
		}
	}
	# Visual Studio 2019 内置的 Build Tools
	elseif (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\*\MSBuild\Current\Bin\MSBuild.exe")
	{
		if (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
		}
		elseif (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe"
		}
		else
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe"
		}
		$script:MsBuildToolsVersion = "Current"
	}
	# Visual Studio 2017 内置的 Build Tools
	elseif (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\*\MSBuild\15.0\Bin\MSBuild.exe")
	{
		if (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe"
		}
		elseif (Test-Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe"
		}
		else
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
		}
		$script:MsBuildToolsVersion = "15.0"
	}
	# Visual Studio 2015 以下版本独立安装的 Build Tools
	elseif (Test-Path "${env:ProgramFiles(x86)}\MSBuild\*\Bin\MSBuild.exe")
	{
		if (Test-Path "${env:ProgramFiles(x86)}\MSBuild\14.0\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\MSBuild\14.0\Bin\MSBuild.exe"
			$script:MsBuildToolsVersion = "14.0"
		}
		elseif (Test-Path "${env:ProgramFiles(x86)}\MSBuild\12.0\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\MSBuild\12.0\Bin\MSBuild.exe"
			$script:MsBuildToolsVersion = "12.0"
		}
		elseif (Test-Path "${env:ProgramFiles(x86)}\MSBuild\10.0\Bin\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:ProgramFiles(x86)}\MSBuild\10.0\Bin\MSBuild.exe"
			$script:MsBuildToolsVersion = "10.0"
		}
	}
	
	# 如果上面的都找不到,则尝试使用系统内置的.NET Framework版本
	if ($script:MSBuildExe -eq "")
	{
		if (Test-Path "${env:SystemRoot}\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:SystemRoot}\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
			$script:MsBuildToolsVersion = "4.0"
		}
		elseif (Test-Path "${env:SystemRoot}\Microsoft.NET\Framework\v3.5\MSBuild.exe")
		{
			$script:MSBuildExe = "${env:SystemRoot}\Microsoft.NET\Framework\v3.5\MSBuild.exe"
			$script:MsBuildToolsVersion = "3.5"
		}
		else
		{
			$script:MSBuildExe = "${env:SystemRoot}\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe"
			$script:MsBuildToolsVersion = "2.0"
		}
	}
}
Set-Msbuild-Tools
Write-Host "`nCurrent Microsoft Build Tools Path: $MSBuildExe" -Foreground $LogForegroundColorStart
Write-Host "Current Microsoft Build Tools Version: $MsBuildToolsVersion" -Foreground $LogForegroundColorEnd

# 定义脚本执行时间/ZIP打包时间
$ExecuteDate = Get-Date
# 定义脚本执行时的最近一条Git Log Commit Id前7位
$GitLogLatestCommitId = (git rev-list Head -n 1 --abbrev-commit)
# 定义脚本日志输出文件路径
$LogFile = "$BuildPath\build_$($ExecuteDate.ToString("yyyyMMddHHmmss")).log"

Write-Host "`nPublish parameters initialize completed." -Foreground $LogForegroundColorEnd

# 开始脚本日志记录
# 注意:脚本执行过程不能中断,否则会导致log file被线程占用,下次执行时会无法删除导致报错
Start-Transcript -Path $LogFile

# 清理缓存文件,垃圾文件
Function Clean-Caches
{
	# 清理log文件
	Write-Host "`nLog files cleaning..." -Foreground $LogForegroundColorStart
	Get-ChildItem -Path "$BuildPath\" -Exclude $LogFile -Include "*.log", "*.zip" -Recurse -Force | Where-Object { $_.FullName -ne $LogFile } | Remove-Item -Force
	Write-Host "Log files clean completed." -Foreground $LogForegroundColorEnd
	
	# 清理项目编译后缓存文件夹
	Write-Host "`nProject build cache files cleaning..." -Foreground $LogForegroundColorStart
	foreach ($packageName in $PackageNames)
	{
		$cacheFolder = "$BuildPath\$packageName"
		Remove-Item -Path $cacheFolder -Recurse -Force -ErrorAction "SilentlyContinue"
	}
	# 清理解决方案
	&$MSBuildExe $SolutionFile /t:Clean
	Write-Host "Project build cache files clean completed." -Foreground $LogForegroundColorEnd
}
Clean-Caches

# 还原NuGet包
Function ReStore-Package
{
	if ($IfUseNuGetReStore -eq "Y")
	{
		if ($IfUpdateNuGetTool -eq "Y")
		{
			Write-Host "`nNuGet tools Start updating..." -Foreground $LogForegroundColorStart
			&$NuGetExe update -Self
			Write-Host "NuGet tools update completed." -Foreground $LogForegroundColorEnd
		}
		else
		{
			Write-Host "Not update NuGet tools." -Foreground $LogForegroundColorEnd
		}
		
		Write-Host "`nNuGet Start ReStoreing..." -Foreground $LogForegroundColorStart
		&$NuGetExe restore $SolutionFile
		Write-Host "NuGet ReStore completed." -Foreground $LogForegroundColorEnd
	}
	else
	{
		Write-Host "`nNot use NuGet tools." -Foreground $LogForegroundColorStart
	}
}
ReStore-Package

# 构建解决方案
Function Build-Solution
{
	Write-Host "`nStart solution building..." -Foreground $LogForegroundColorStart
	&$MSBuildExe $SolutionFile "/t:Build" "/toolsversion:$MsBuildToolsVersion" "/verbosity:$LogLevel" "/logger:FileLogger,Microsoft.Build;logfile="""$BuildPath\$($SolutionName)_Build_$($Configuration)_$($ExecuteDate.ToString("yyyyMMddHHmmss")).log"""" "/p:Configuration=$Configuration"
	Write-Host "Build solution completed." -Foreground $LogForegroundColorEnd
}
Build-Solution

# 发布项目集
Function Publish-Projects
{
	# Win项目发布到本地文件夹
	foreach ($projectName in $WinProjectNames)
	{
		Write-Host "`nStart $projectName project publishing..." -Foreground $LogForegroundColorStart
		&$MSBuildExe "$($SolutionPath)\$($projectName)\$($projectName).csproj" "/t:Rebuild" "/toolsversion:$MsBuildToolsVersion" "/verbosity:$LogLevel" "/logger:FileLogger,Microsoft.Build;logfile="""$BuildPath\$($projectName)_Publish_$($Configuration)_$($ExecuteDate.ToString("yyyyMMddHHmmss")).log"""" "/p:Configuration=$Configuration" "/p:OutputPath=$($BuildPath)\$($projectName)"
		Write-Host "Publish $projectName project completed." -Foreground $LogForegroundColorEnd
	}
	
	# Web项目发布到本地文件夹
	foreach ($projectName in $WebProjectNames)
	{
		Write-Host "`nStart $projectName project publishing..." -Foreground $LogForegroundColorStart
		&$MSBuildExe "$($SolutionPath)\$($projectName)\$($projectName).csproj" "/t:WebPublish" "/verbosity:$LogLevel" "/logger:FileLogger,Microsoft.Build;logfile="""$BuildPath\$($projectName)_Publish_$($Configuration)_$($ExecuteDate.ToString("yyyyMMddHHmmss")).log"""" "/p:Configuration=$Configuration" "/p:WebPublishMethod=FileSystem" "/p:DeleteExistingFiles=True" "/p:publishUrl=$($BuildPath)\$($projectName)"
		Write-Host "Publish $projectName project completed." -Foreground $LogForegroundColorEnd
	}
}
Publish-Projects

# ZIP打包
Function Zip-Package
{
	foreach ($packageName in $PackageNames)
	{
		Write-Host "`nStart $packageName project packing..." -Foreground $LogForegroundColorStart
		
		$targetFolder = "$BuildPath\$packageName\"
		# exclusion rules. Can use wild cards (*)
		$exclude = "*.config", "*.bak", "*.log", "*.zip" #, "*.pdb", "*.xml", "bin\*.config"
		# get files to compress using exclusion filer
		$files = Get-ChildItem -Path $targetFolder -Exclude $exclude
		
		# compress
		$destination = "$BuildPath\$($packageName)_$($GitLogLatestCommitId)_$($ExecuteDate.ToString("yyyyMMddHHmmss")).zip"
		Compress-Archive -Path $files -DestinationPath $destination -CompressionLevel Optimal
		
		Write-Host "Pack $packageName project completed." -Foreground $LogForegroundColorEnd
	}
}
Zip-Package

# 结束脚本日志记录
Stop-Transcript
作者:VAllen
出处:http://www.cnblogs.com/vallen
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
唯有偏执者得以生存。
posted @ 2019-09-07 16:41  VAllen  阅读(758)  评论(0编辑  收藏  举报