- 查找最高版本的MsBuildTools。
- 清理緩存垃圾。
- 還原NuGet包。
- 構建解決方案。
- 按項目發布程序到本地。
- 按項目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