---
title: "優化 .NET MVC 部署流程：自動化建置與手動佈署"
description: "說明如何利用 Jenkins Pipeline 搭配 MSBuild 自動建置舊版 .NET MVC 專案，並透過 Beyond Compare 手動比對差異後佈署。"
canonical_url: "https://blog.markkulab.net/post/net-mvc-auto-build-manual-deploy"
author: "Mark Ku"
author_url: "https://blog.markkulab.net/author/mark-ku"
site: "Mark Ku's Blog"
date_published: "2024-09-03 01:01:35 +0800"
category: "DevOps"
tags: ["jenkins", "msbuild", "dotnet", "cicd", "devops", "deploy", "powershell"]
language: "zh-TW"
license: "CC BY 4.0"
license_url: "https://creativecommons.org/licenses/by/4.0/"
attribution: "轉載或引用請註明作者並附上原文連結"
---

# 優化 .NET MVC 部署流程：自動化建置與手動佈署

## 時空背景
目前公司內大部的系統都能夠容器化，但總有些舊網站，最舊也最大也最賺錢，暫時無法做技術昇級，但人數一多手動佈版，都會遇到有人漏提交 Binary，因此想把自動建置的部份自動化，優化佈版流程，同時也減少錯誤帶來的影響。  

因為是舊系統及Net Mvc framework 的舊框架，無法容器化，全自動佈版，會有點風險，因此這邊佈署的部份，仍然還是採用手動。

## 目標
* 當有人 Push 任何code 到 Master 分支時，Jenkins 就會自動建置，並將建置完的 Binary，自動提交及推送到 Github。
* 生產環境寫一個腳本，透過 Git 將最新的準備佈署的Binary 拉下來，接著透過 Beyond compare 比較 binary 差異，最後交由人工手動佈版。

## 環境說明
因為是舊系統，Jenkins 安裝在 Windows server 上。

## 首先，找回 MS Build 
我們都知道NET MVC 的建置是透過Msbuild 這個工具，依據對照的 Visual Studio 2019 版本找到對照的版本是MSBuild 16 ，但在微軟的網頁，目前舊版 Msbuild tool 下載連結都找不太到下載連結，最後我從[MSDN 訂閱帳號](https://my.visualstudio.com/Downloads?q=visual%20studio%202019)，裡找回舊版的 Visual stdio 2019 下載連結。  
![MSDN](https://blog.markkulab.net/content/markku/posts/net-mvc-auto-build-manual-deploy/images/msdn.png)

安裝記得勾選 Desktop development with c++
![Installation](https://blog.markkulab.net/content/markku/posts/net-mvc-auto-build-manual-deploy/images/installation.png)


## 設定 Jenkins 的MS Build 路徑
MS Build 安裝路徑是
Visual studio 2019 一起安裝的MSBuild.exe 路徑是
```
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin
```
## 下載[nuget.exe ](https://www.nuget.org/downloads)

下載 Nuget.exe 至 
```
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin 
```

## 下載並安裝 [.NET Framework 4.8 Developer Pack ](https://dotnet.microsoft.com/en-us/download/dotnet-framework/net48)

## 首先，至 Github repo 設定webhook 當程式commit 時通知 Jenkins 自動建置
![Github webhook setting](https://blog.markkulab.net/content/markku/posts/net-mvc-auto-build-manual-deploy/images/github-webhook.png)
```
http://jks.xxx.com/github-webhook/
```
## 接著，Jenkins 設定自動建置 pipeline
建立Job >選擇New Item > Pipeline，並設定 Github Project。

![github project setting](https://blog.markkulab.net/content/markku/posts/net-mvc-auto-build-manual-deploy/images/github-project-setting.png)

```
properties([pipelineTriggers([githubPush()])])

pipeline {
	agent any

	environment {		
	}
	
	options {
		buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '3', daysToKeepStr: '', numToKeepStr: '3')
	}

	stages {
	    stage('Cleanup Directories') {
            steps {
                script {
                    // Delete the 'Api' and 'Artifact' directories
                    dir('Api') {
                        deleteDir()
                    }
                    dir('Artifact') {
                        deleteDir()
                    }
                    
                    dir('Publish') {
                        deleteDir()
                    }
                    echo "Deleted Api and Artifact directories."
                }
            }
        }
	
	    stage("GitHub Pull - Ｎet mvc api") {
            steps {
                dir('Api') {
                    git(
                        branch: 'master',
                        credentialsId: 'xxxx-xxxx-xxxx',
                        url: 'git@github.com:iRobot/MVC.Api.git'
                    )
                }
            }
        }
		
		 stage("GitHub Pull - Artifact") {
            steps {
                dir('Artifact') {
                    git(
                        branch: 'main',
                        credentialsId: 'xxxx-xxxx-xxxx',
                        url: 'git@github.com:iRobot/Artifact.git'
                    )
                }
            }
        }
        
    stage('Restore nuget') {
        steps {
        script {
            bat 'echo Current Directory: %CD%'
            bat 'echo Workspace Directory: %WORKSPACE%'
            bat '"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\MSBuild\\Current\\Bin\\nuget.exe" restore ".\\Api\\IRobot.WebCore\\IBuyPower.WebCore.sln"'
        }
        }
    }
    
    stage('Build') {
            steps {
                script {
                    // Define the MSBuild path and solution file
                    def msBuildPath = '"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\MSBuild\\Current\\Bin\\MSBuild.exe"'
                    def solutionPath = '".\\api\\IRobot.WebCore\\IRobot.WebCore.sln"'

                    // Build command with all necessary parameters
                    def buildCommand = "${msBuildPath} ${solutionPath} /t:Clean,Build /p:Configuration=enUSLive /p:DeployOnBuild=True /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:DeleteExistingFiles=True /p:OutDir=\"%WORKSPACE%\\Publish\" /p:ExcludeGeneratedDebugSymbol=True -verbosity:minimal"

                    // Execute the build command
                    bat script: buildCommand, returnStatus: true
                }
            }
    }
    
     stage("Copy to Artifact") {
            steps {
                script {
                    
                    def buildCommand =  "robocopy \"%WORKSPACE%\\Publish\\_PublishedWebsites\\Core.Web\" \"%WORKSPACE%\\Artifact\" /E /COPY:DAT /MT:100"

                    // Execute the build command
                    bat script: buildCommand, returnStatus: true
                }
            }
        
    }
    
    stage('Check for Changes and Commit') {
    steps {
        dir('Artifact') {
            script {
                // Set local git configuration for user identity
                bat "git config user.email \"jenkins@example.com\""
                bat "git config user.name \"Jenkins CI\""

                // Stage all changes
                bat "git add ."

                // Commit with a timestamp
                bat "git commit -m \"Automated commit at ${new Date().format('HH:mm:ss')} by Jenkins\""

                // Attempt to push changes to remote repository
                def pushResult = bat(script: "git push --set-upstream origin main", returnStdout: true, returnStatus: true)
                if (pushResult != 0) {
                    echo "Failed to push changes. Error Code: ${pushResult}"
                }
            }
        }
    }
}	
}
}
```	
	
## 手動佈版
因為是舊系統及Net Mvc的舊框架，無法容器化，全自動佈版，會有點風險，因此這邊佈署的部份，仍然還是採用手動。

### 再安裝 Beyond Compare
### 撰寫powerhsell  deploy.ps1
```
git pull 

$LOCAL = "C:\Workspace\USApiArtifact\bin"
$REMOTE = "C:\inetpub\Core.Web\bin"

$env:Path = "C:\Program Files\Beyond Compare 4\" 
$filters = "/filters=-web.config"
BCompare.exe /excludefilter="web.config"  "$LOCAL" "$REMOTE" $filters
```
## 最後，執行後就能透過，Beyond compare 去比較此次佈版的dll 是不是和所想的一樣，最後透過右鍵 Copy to Right 來佈署新版應用程式。
![Final](https://blog.markkulab.net/content/markku/posts/net-mvc-auto-build-manual-deploy/images/beycond-copare.png)

---

## 關於本文與作者

本文出自 [Mark Ku's Blog](https://blog.markkulab.net/post/net-mvc-auto-build-manual-deploy)

授權條款： [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — 轉載或引用請註明作者並附上原文連結

### 關於作者

**[Mark Ku](https://blog.markkulab.net/author/mark-ku)** — Software Solution Provider

- 10+ 年資深軟體工程師，現為 AI 應用 Builder
- 專注大型平台架構設計，從北美電商到AI SaaS訂閱收費系統
- 結合 AI Agent 與自動化，打造高效可演進的產品技術基礎

### 作者開發的免費工具

以下工具皆可免費使用：

- [免費 PDF 簽名工具](https://blog.markkulab.net/tools/pdf-sign): 線上 PDF 簽名工具，瀏覽器內完成手繪、打字、上傳簽名，可拖曳放置、縮放、下載。所有處理都在你的裝置完成，檔案不會上傳。
- [VS Code Refactory](https://blog.markkulab.net/tools/refactory): Refactory 是一款 VS Code 重構擴充套件：34 個重構動作、37 條 code smell 檢查、Code Health 儀表板、18 種語言、534 支測試。懂你的專案慣例：介面放哪、DI 註冊寫在哪、'use client' 該不該加；還會用 git 修改頻率 × 複雜度排出「該先修哪個檔案」，並一鍵把壞味道交給你自己電腦上的 Claude Code 修。免費使用，原始碼不離開你的機器。
- [DB-Kit 資料庫管理工具](https://blog.markkulab.net/tools/db-kit): DB-Kit 是一個用 Tauri + Rust + React 打造的輕量跨平台資料庫管理工具，用單一一致的介面同時管理 MySQL、MariaDB、PostgreSQL、SQL Server、Oracle、SQLite、MongoDB、Redis、Kafka、Elasticsearch 與 RabbitMQ 十一種資料來源：連線密碼以 OS keychain 加密、SSH Tunnel、完整 CRUD、視覺化查詢建構器、多結果集同時顯示、跨連線資料傳輸與比對同步、Excel / CSV 匯入匯出、執行計畫視覺化、ER 圖、排程備份、SQL 壓力測試（p50～p99 延遲百分位）、15 條規則的 SQL 審查、Kafka 訊息瀏覽與監控告警；繁中 / 英文雙語介面，內建 AI 助手（自然語言生成 SQL、AI 審查與調校建議）與命令列工具 dbk。免費開源（MIT），提供 Windows / macOS / Linux 安裝檔。
- [VS Code Super Mermaid](https://blog.markkulab.net/tools/super-mermaid): Super Mermaid 是一款 VS Code 擴充套件：開箱即用的漂亮 Mermaid 圖表，自動上色、即時預覽、滑鼠平移縮放、PNG / SVG 高解析匯出，內建 21 種範本與多種主題。免費開源（MIT）。
- [React Super Mermaid](https://blog.markkulab.net/tools/react-super-mermaid): react-super-mermaid 是一個開源 React 元件庫：一行 <MermaidViewer> 即可渲染漂亮的 Mermaid 圖表，內建 colorful / sketch 主題、平移縮放、圖內搜尋、SVG / PNG 高解析匯出。輕量、SSR 安全、完整 TypeScript 型別。免費開源（MIT）。
- [Jira / Confluence Super Mermaid](https://blog.markkulab.net/tools/jira-super-mermaid): Atlassian Forge app：在 Jira issue 與 Confluence 內文直接寫 Mermaid 語法，畫流程圖、時序圖、狀態機與甘特圖。11 種圖表、SVG / PNG 匯出、明暗主題、完整中日韓文字支援。取得 Runs on Atlassian 資格：圖表存在你自己的站台，app 不呼叫任何第三方服務。免費，即將上架 Atlassian Marketplace。
- [Mermaid 線上預覽](https://blog.markkulab.net/tools/mermaid-preview): 在瀏覽器裡寫 Mermaid、即時看圖，整張圖表壓進網址就能分享。免註冊、不上傳伺服器，相容 mermaid.live 的分享連結。
- [React Intl Phone Number](https://blog.markkulab.net/tools/react-intl-phone-number): react-intl-phone-number 是一個開源 React 元件：framework-agnostic、不依賴 antd，提供 E.164 進出、可搜尋國旗 / 國碼下拉、可配置驗證等級（strict / mobile-strict / loose）、可主題化 CSS 與 i18n，電話邏輯由 google-libphonenumber 驅動。輕量、完整 TypeScript 型別。免費開源（MIT）。
- [Uptime Kuma Cluster](https://blog.markkulab.net/tools/uptime-kuma-cluster): 把單機版 Uptime Kuma 改造成高可用叢集：OpenResty + Lua 智慧負載平衡、MariaDB 共享狀態、健康檢查與自動 Failover，附叢集管理 REST API，一行 Docker Compose 啟動。免費開源（MIT）。
- [特教專案](https://blog.markkulab.net/education): 為特殊教育學生製作的學習教材

### 每日 Podcast

- [科技新鮮事](https://blog.markkulab.net/category/tech-news): 每日精選 AI 與科技趨勢，透過語音摘要快速掌握最新技術動態，涵蓋 AI 應用、軟體架構、DevOps 與工程實戰。 — RSS: https://blog.markkulab.net/feed.xml
- [AI股市蝦聊](https://blog.markkulab.net/category/ai-stock-chat): 每個交易日用 AI 分析台股盤勢，以雙人對話聊當天的盤中觀察與隔日預測。 — RSS: https://blog.markkulab.net/ai-stock-chat/feed.xml

### 電子報

[訂閱電子報](https://blog.markkulab.net/subscribe) — 第一時間收到新文章通知，無垃圾信、隨時可取消訂閱。
