當AL.exe或CSC.exe生成PE檔案程式集時,還在PE檔案中內嵌了一個標準的Win32版本資源。使用者可以檢視檔案屬性找到該資源。應用程式程式碼還可以在執行時呼叫System.Diagnostics.FileVersionInfo的GetVersionInfo靜態方法來得到資源資訊。下圖顯示了JeffTypes.dll屬性對話方塊的Details選項卡。
當生成程式集時,我們應該使用自定義特性來設定其版本資源欄位。這些自定義欄位應該被應用在程式集級別上。下面的程式碼將產生如上圖所示的版本資訊:
using System.Reflection; // FileDescription version information: [assembly: AssemblyTitle("JeffTypes.dll")] // Comments version information: [assembly: AssemblyDescription("This assembly contains Jeff's types")] // CompanyName version information: [assembly: AssemblyCompany("Wintellect")] // ProductName version information: [assembly: AssemblyProduct("Wintellect (R) Jeff's Type Library")] // LegalCopyright version information: [assembly: AssemblyCopyright("Copyright (c) Wintellect 2010")] // LegalTrademarks version information: [assembly:AssemblyTrademark("JeffTypes is a registered trademark of Wintellect")] // AssemblyVersion version information: [assembly: AssemblyVersion("3.0.0.0")] // FILEVERSION/FileVersion version information: [assembly: AssemblyFileVersion("1.0.0.0")] // PRODUCTVERSION/ProductVersion version information: [assembly: AssemblyInformationalVersion("2.0.0.0")] // Set the Language field (discussed later in the "Culture" section) [assembly:AssemblyCulture("")]
不幸的是,Windows Explorer屬性對話方塊並不包含上述全部特性。特別是如果能顯示AssemblyVersion特性的值就完美了,因為CLR再家在程式集的時候會使用這個值。
下面的表顯示了版本資源欄位和對應的自定義特性。如果你使用AL.exe生成程式集,你可以使用命令列開關來代替使用自定義特性的方式設定這些資訊。表的第二列為每個版本資源欄位所對應的AL.exe命令列開關。要注意的是C#編譯器沒有提供一些命令列開關,因此使用自定義特性來設定這些資訊使首選。
版本資源 | AL.exe開關 | 自定義特性/註釋 |
FILEVERSION | /fileversion | System.Reflection.AssemblyFileVersionAttribute |
PRODUCTIVERSION | /productversion | System.Reflection.AssemblyInformationalVersionAttribute |
FILEFLAGSMASK | (none) | 總是設定為VS_FFI_FILEFLAGSMARK(在WinVer.h中位0x0000003F) |
FILEFLAGS | (none) | 總是為0 |
FILEOS | (none) | 目前總是為VOS_WINDOWS32 |
FILETYPE | /target | 如果指定為/target:exe或/target:winexe則設定為VFT_APP,如果指定為/target:library,則設定為VFT_DLL |
FILESUBTYPE | (none) | 總是設定為VFT2_UNKNOWN(該欄位對於VFT_APP和VFT_DLL來說沒有意義) |
AssemblyVersion | /version | System.Reflection.AssemlbyVersionAttribute |
Comments | /description | System.Reflection.AssemblyDescriptionAttribute |
CompanyName | /company | System.Reflection.AssemblyCompanyAttribute |
FileDescription | /title | System.Reflection.AssemblyTitleAttribute |
FileVersion | /version | System.Reflection.AssemblyFileVersionAttribute |
InternalName | /out | 設定為指定的輸出檔案的名稱(不含副檔名) |
LegalCopyright | /copyright | System.Reflection.AssemblyCopyrightAttribute |
LegalTrademarks | /trademark | System.Reflection.AssemblyTrademarkAttribute |
OriginalFilename | /out | 設定為輸出檔案的名稱(不含路徑) |
PrivateBuild | (none) | 總是為空白(blank) |
ProductName | /product | System.ReflectionAssemblyProductAttribute |
ProductVersion | /productversion | System.Reflection.AssemblyInformationVersionAttribute |
SpecialBuild | (none) | 總是為空白(blank) |
當你在Visual Studio中建立C#專案時,會自動生成一個Assembly.cs檔案。該檔案包含所有本節所介紹的程式集版本特性,以及一些第3章涵蓋的特性。你可以開啟AssemblyInfo.cs檔案,修改程式集特定的資訊。Visual Studio還提供了一個對話方塊可以對程式集版本資訊進行編輯。在Solution Explorer中右擊專案屬性條目,選擇Application選項卡,點選Assembly Infomation,可以看到如下圖所示的對話方塊。
版本號
我們看到一個程式集可以應用多個版本號。這些版本號的格式都使一致的,共包含4個部分。
前兩個數字組成了版本的公共部分。本例中程式集的公共版本號即為2.5。第三個數字719指明瞭程式集的生成次數。如果每天都生成程式集,那麼這個數字每天都應該增加。最後一個數字2指明瞭生成的版本。如果由於某些原因(如解決了一個影響其他部分的大bug)在一天內生成了兩次,那麼應該增加這個數字。
微軟使用的就是這種版本號模式,並且也強烈建議大家這麼做。未來的CLR版本將對載入新的程式集版本,以及在新版本與當前應用不相容時回滾到舊版本提供更好的支援。要做到這種版本化支援,CLR要求修補了bug的程式集的版本要有相同的主次版本號,生成和修訂版本號要指明包含了更新的服務版本。當載入程式集時,CLR將自動查詢最近安裝的與主次版本號匹配的程式集的服務版本。
你會發現一個程式集包含三個相關的版本號。這導致了很多混淆。每個版本號的意圖和用法如下:
- AssemblyFileVersion:該版本號儲存在Win32版本資源中。它只是一個資訊,CLR不檢查該版本號。典型地,可以設定主次版本號來標識希望被公眾看到的版本。然後每生成一次,就增加生成和修訂版本號。理想情況下,微軟工具(CSC.exe或AL.exe)會自動更新生成版本號和修訂版本號(根據生成的日期和時間),但事實並不是這樣。該版本號可以在Windows Explorer中看到,並用來識別指定程式集的版本。
- AssemblyInformationVersion:該版本號同樣儲存在Win32版本資源中,也是作為資訊存在。CLR既不檢查也不關心它。該版本號用來標識包含該程式集的產品的版本。例如,一個產品的2.0版本可能包含多個程式集,其中一個新的程式集由於沒有隨產品的1.0版本釋出而被標識為1.0版本。典型地,我們可以設定該版本號的主次部分來表示產品的公共版本。然後在每次打包成一個完整的產品時,增加版本號的生成和修訂部分。
- AssemblyVersion:該版本號儲存在AssemblyDef清單後設資料表中。在繫結強命名程式集時,CLR會使用該版本號。它用來唯一標識一個程式集。當開始開發一個程式集時,你需要設定主、次、生成、修訂版本號,並且在開始開發程式集的下一個部署版本之前,不應該改變它們。在生成一個程式集時,該程式集所引用的所有程式集的版本號會內嵌到AssemblyRef表的條目中。這意味著一個程式集一個程式集將和它引用的程式集的特定版本緊緊繫結在一起。