.NET 3.5 Windows Forms 類別庫升級至 .NET 6

我把一個大約十年沒更新的 Windows Forms 控制項從 .NET 3.5 升級至 .NET 6,然後透過 AppVeyor 平台來自動建置並發布套件至 NuGet.org。這裡記錄此過程的一些重點細節。

動機

之所以動手做這件事,是因為我的一個 Windows app 有用到這個 Windows Forms 控制項:SourceGrid。為了讓自己的軟體專案能夠跟上 .NET 演進的步調,便著手將自己的 .NET 專案升級 至 .NET 6。於是乎,我的專案所用到的第三方套件,只要我發現沒有支援 .NET 6 的,而且能找到原始碼,我就會嘗試動手去升級那個第三方套件。

在 GitHub 上面可以找到數個版本的 SourceGrid 原始碼,而我原先使用的是 siemens/sourcegrid。為了將此套件從 .NET 3.5 升級至 .NET 6,我有了自己的 fork:huanlin/SourceGrid

將 SourceGrid 升級至 .NET 6 的工作接近完成時,我覺得其中有一些技術細節值得記下來。當時第一個念頭是:何不用影片來記錄?於是我最初完成的是影片。但後來發現影片還是有一些細節遺漏了,若要重新錄製,時間成本太高,所以有了這篇文章,作為影片的補充說明。

影片

要先說的是,這是我的第一個用英語講述的影片。我自認口條不佳,英語也沒有到夠好的程度,只是順便讓自己多練一下英語。如果你覺得影片解說得不夠清楚,請多包涵,也可以在本文稍後的補充說明文字當中找看看有沒有你想知道的東西。若有任何建議,歡迎在本文或影片下方留言。

影片放在我的 Youtube 頻道:


文字補述

在升級 SourceGrid 專案時,我做了以下幾項修改:
  1. 把三個 .csproj 檔案升級為 SDK-style 格式。使用的工具是 .NET Upgrade Assistant
  2. 加入必要的組件參考。
  3. 有些程式碼和 API 已經過時,無法通過編譯,必須修改。例如:MenuItem、ContextMenu。
  4. 移除一些沒有用到的程式碼和檔案。
  5. 使用 MinVer 來自動處理專案的版本編號。(好用,推薦!)
  6. 修改 appveyor.yml 來自動發布新版本套件至 NuGet.org。

我也修改了 README.md,把新版範例程式的截圖放進去,如下圖:



接下來,針對幾項我認為有必要進一步說明的細節來稍作補充。

.NET 升級助理(Upgrade Assistant)

我發現,每當 .NET 升級助手執行到「分析程式碼」這個步驟時,似乎就當掉了。所以我每次都只執行了前面 4 個步驟,也就是:
  1. Backup project
  2. Convert project to SDK style
  3. Update TFM
  4. Update NuGet Package
剩下的轉換與清理工作,就由我自行處理了。 比如說,使用此工具升級專案之後,發現還有不少多餘的標籤存在 .csproj 檔案裡,雖然不影響編譯結果,但總是希望檔案內容清爽乾淨些,所以也花了一點時間清除那些冗餘的標籤。

加入必要的組件參考

SourceGrid 是 Windows Forms 控制項,故需加入 Microsoft.Windows.Compatibility 套件來協助升級至 .NET 6。將此套件加入專案之後,每當建置專案完成,你會看到輸出目錄會多出一堆看似根本沒用到的 DLL 檔案,而且這些檔案的名稱大多是以 System.* 起頭,例如 System.Data.Odbc.DLL。我們可以從 Microsoft.Windows.Compatibility 套件的 dependencies 清單得知它會給我們的專案增加哪些 DLL 檔案。以 .NET 6.0 專案為例,其相依檔案清單如下(摘自 NuGet.org):

Microsoft.Win32.Registry.AccessControl
Microsoft.Win32.SystemEvents
System.CodeDom
System.ComponentModel.Composition
System.ComponentModel.Composition.Registration
System.Configuration.ConfigurationManager
System.Data.Odbc
System.Data.OleDb
System.Data.SqlClient
System.Diagnostics.EventLog
System.Diagnostics.PerformanceCounter
System.DirectoryServices
System.DirectoryServices.AccountManagement
System.DirectoryServices.Protocols
System.Drawing.Common
System.IO.Packaging
System.IO.Ports
System.Management
System.Reflection.Context
System.Runtime.Caching
System.Security.AccessControl
System.Security.Cryptography.Pkcs
System.Security.Cryptography.ProtectedData
System.Security.Cryptography.Xml
System.Security.Permissions
System.ServiceModel.Duplex
System.ServiceModel.Http
System.ServiceModel.NetTcp
System.ServiceModel.Primitives
System.ServiceModel.Security
System.ServiceModel.Syndication
System.ServiceProcess.ServiceController
System.Speech
System.Text.Encoding.CodePages
System.Threading.AccessControl
System.Web.Services.Description

Microsoft.Windows.Compatibility 套件雖然方便,但是建立安裝程式的時候,如果不打算把上列 DLL 檔案全包進去,就得花一番工夫來揀選了。

另外值得一提的是,我另外加入了 MinVer 套件來自動管理組件版本。這個工具相當簡單易用,在大部分的情況下,只需要知道底下兩點就行了:
  1. 將 MinVer 套件加入專案。
  2. 每當要發布新版本時,亦即每當你希望讓你的 .NET 應用程式有一個新的版本號碼時,只要在專案的 Git repo 加入一個新 tag,並以版本號碼來命名這個 tag,例如 "1.0.3"。那麼下次建置專案時,應用程式的版本編號就會是 1.0.3。
就這樣而已!我覺得比 GitVersion 更簡單、更好用。

當然,MinVer 也有支援所謂的搶鮮版(alpha release 或 pre-release)的版本編號,而且提供了一些選項來滿足各種不同的需求。相關細節,在 MinVer 的 README 文件裡面都可以找到。

AppVeyor.yml

放在 Git repo 根目錄底下的 AppVeyvor.yml 是一個組態檔,可用來控制 AppVeyor 的自動建置程序。在這次升級過程中,由於加入了 MinVer 來控制專案的版本編號,而 MinVer 是透過 Git 標籤(tag)來運作,因此,我在這個 .yml 檔案中加入了以下設定:


skip_non_tags 設定為 true 是在告訴 AppVeyor:跳過沒有 tag 的變動。也就是說,只對有 tag 的程式碼版本進行建置。

deploy 區段的部分,provider 指定為 NuGet,代表要發布至 NuGet 伺服器。「on APPVEYOR_REPO_TAG: true」的意思是只有在 push tag 所引發的建置才執行這個 deploy 區段的工作。

api_key 則是我自己的 NuGet API key,而且是經過 AppVeyor 加密過的 key。加密的作法可參考下圖:



有關 AppVeyor 的環境變數,可參閱官方文件:Environment variables

結語

原先的 SourceGrid 版本號碼是 4.4.0,已大約九年沒有變動。我升級至 .NET 6.0 的版本,在控制項的部分並沒有增加新功能,但還是採用了 6.0.x 這樣比較大的版號跳動,主要還是為了方便識別此版本可支援 .NET 6。此作法或有可議之處,歡迎提供建議。我已在原始 SourceGrid 專案的 GitHub 頁面留言提供我的 fork 連結,如果我的 fork 能夠獲得採納,合併至原先的 repo,那就再好不過了。

沒有留言:

技術提供:Blogger.
回頂端⬆️