.NET Framework 4.x 程序到底運行在哪一個 CLR 版本之上

轉載至 .NET Framework 4.x 程序到底運行在哪一個 CLR 版本之上html

當咱們編譯程序目標框架選爲 .NET Framework 4.5/4.6/4.7/4.8 時,CLR 運行時是如何判斷咱們究竟應該用哪個 .NET Framework 呢?.NET Framework 的版本到底由哪些部分組成?咱們編譯 .NET Framework 時選擇的版本決定了什麼?web


讓我對這個問題產生興趣的緣由是:安全

  • 我將程序編譯的目標框架選爲 .NET Framework 4.8;在一臺安裝了 .NET Framework 4.6 的電腦上提示缺乏 .NET Framework 4.8;刪除了隨編譯一塊兒生成的 app.config 文件後程序可以正常運行。
  • 另外一個程序,我明明將程序編譯的目標框架選爲 .NET Framework 4.5,但在一臺沒有安裝任何額外 .NET Framework 的 Windows 7 的電腦上提示缺乏的是 .NET Framework 4.0。

這裏的疑點在於爲何以上兩種看似相似的狀況,提示的框架版本卻不一樣。其中的 app.config 文件成爲了調查此問題的突破口。app

配置支持的運行時

觀察程序附帶的 app.config 文件,咱們發現支持的運行時版本是 v4.0,sku 版本是 4.8。框架

<configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /> </startup> </configuration> 

疑點:ide

  1. 爲何咱們基於 .NET Framework 4.8 開發的程序運行時版本是 4.0?
  2. sku 是什麼?

微軟的官方文檔給了咱們解答:supportedRuntime Elementpost

  • version:用於指定此應用程序支持的公共語言運行時(CLR)的版本。
  • sku:stock-keeping unit(官方中文爲「庫存單位」,然而依然不懂這個詞的意思),用於指定此應用程序支持的 .NET Framework 發行版本。

version 的值可取:ui

.NET Framework 版本 version 值
忽略早期版本 忽略早期版本
2.0 「v2.0.50727」
3.0 「v2.0.50727」
3.5 「v2.0.50727」
3.5 「v2.0.50727」
4.0-4.8 「v4.0」

sku 的值可取:spa

.NET Framework version sku 值
4.0 「.NETFramework,Version=v4.0」
忽略中間版本 忽略中間版本
4.5 「.NETFramework,Version=v4.5」
4.5.1 「.NETFramework,Version=v4.5.1」
4.5.2 「.NETFramework,Version=v4.5.2」
4.6 「.NETFramework,Version=v4.6」
4.6.1 「.NETFramework,Version=v4.6.1」
4.6.2 「.NETFramework,Version=v4.6.2」
4.7 「.NETFramework,Version=v4.7」
4.7.1 「.NETFramework,Version=v4.7.1」
4.7.2 「.NETFramework,Version=v4.7.2」
4.8 「.NETFramework,Version=v4.8」

因而咱們發現,其實不管咱們將程序的目標框架選爲 .NET Framework 的哪個 4.x 版本,CLR 運行時都是用 v4.0 表示的。微軟的描述是:.net

對於支持 .NET Framework 4.0 或更高版本的應用程序,version 屬性指示 CLR 版本,這是 .NET Framework 4 及更高版本的通用版本,而 sku 屬性指示應用程序所針對的單個 .NET Framework 版本。

其實看到這裏咱們就能有一個看似不錯的解釋:

  1. 不管咱們選擇的目標框架是 .NET Framework 4.x 的哪個版本,用於指定 CLR 運行時版本的 version 值都是 v4.0;
  2. CLR 運行時會根據配置文件的 sku 值決定應該採用那一組運行庫來爲程序運行提供支持。

.NET Framework 的組成以及各部分的版本

咱們須要尋找到 .NET Framework 的本質,否則如此錯綜複雜的版本號系統真把我搞懵了。

微軟在 .NET Framework Versions and Dependencies 中說到:

每一個版本的 .NET Framework 都包含公共語言運行時 (CLR)、基礎庫和其餘託管庫。

因而咱們談論 .NET Framework 的版本其實應該分三個不一樣的部分來談:

每一個新版本的 .NET Framework 都會保留早期版本中的功能並會添加新功能。 CLR 有其本身的版本號標識。 雖然 CLR 版本並不老是遞增的,但 .NET Framework 版本號在每次發佈時都會遞增。 例如,.NET Framework 四、4.5 和更高版本包含 CLR 4,而 .NET Framework 2.0、3.0 和 3.5 包含 CLR 2.0。 (沒有版本 3 的 CLR。)

從官方文檔給出的表格當中咱們能夠確信:.NET Framework 4.0/4.5/4.6/4.7 包含的 CLR 版本都是 4.0。

CLR 的更新

然而,不相信微軟的 CLR 能夠徹底沒有 BUG,既然 CLR 版本都是 4.0,那麼微軟對 CLR 運行時的更新怎麼處理?安裝了 .NET Framework 4.5/4.6/4.7 會如何提高 CLR 的穩定性和安全性?

在 Targeting and Running .NET Framework apps for version 4.5 and later 中,解釋了 CLR 的更新機制——就地更新(in-place update)。這篇文章 .NET 4.5 is an in-place replacement for .NET 4.0 對這種就地更新方式有比官方文檔更詳細的解釋,而且還附帶本身的一些試驗(含代碼)。不過文章是 2012 年寫的,部分結論如今看來已通過時(由於在個人 Windows 10 配 .NET Framework 4.7 上結論已經不同),不過對我理解就地更新自己很是有幫助,也爲後續調查提供了更清晰的思路。

微軟對 .NET Framework 4.x 框架就地更新的說明是:

.NET Framework 4.5 是替代計算機上的 .NET Framework 4 的就地更新,一樣,.NET Framework 4.5.1 4.5.二、4.六、4.6.一、4.6.二、4.七、4.7.一、4.7.二、4.8 是對 .NET Framework 4.5 的就地更新,這意味着它們將使用相同的運行時版本,可是程序集版本會更新幷包括新類型和成員。 在安裝其中某個更新後,你的 .NET Framework 4.NET Framework 4.5 或 .NET Framework 4.6 應用應繼續運行,而無需從新編譯。 可是,反過來則不行。

也就是說,不管咱們在開發時指定目標框架的版本是 4.x 的哪個,在運行時,CLR 環境都是 4.0。可是新的 .NET Framework 會帶來更新版本的 CLR,這個 CLR 會直接替換掉舊的 CLR。.NET 4.5 is an in-place replacement for .NET 4.0 文章中 .NET Framework 基礎庫也是就地更新的;但我實際實驗的狀況是每個不一樣的 .NET Framework 基礎庫有本身單獨的文件夾,目前尚不清楚這個改變是從 .NET Framework 的哪個版本開始的,但必定是 4.5.一、4.5.二、4.6 這三個版本中的一個。

每個不一樣的 .NET Framework 基礎庫有本身單獨的文件夾

解決一開始的疑問

因而,本文一開始的疑問就所有明晰了:

  1. 不論是 .NET Framework 4.5 的仍是 4.8 的那兩個程序,都是靠 4.0 版本的公共語言運行時(CLR)運行起來的;
  2. 若是沒有安裝 4.0 版本的 CLR,則會彈出提示須要安裝 .NET Framework 4.0 版本才能運行,而無論咱們的程序目標框架是 .NET Framework 4.x 的哪個版本;
    • 雖說文案說的是 .NET Framework,但其實須要的是 CLR
  3. 若是已經安裝有 4.0 版本的 CLR(可能隨 .NET Framework 4.5/4.6 安裝),咱們程序的目標框架是 .NET Framework 4.8,但 .NET Framework 基礎庫並無安裝 4.8 版本,則運行時會提示須要安裝 .NET Framework 4.7;
    • 這個提示是 4.0 版的 CLR 彈出的,是根據 supportedRuntime 中指定的 sku 值來決定的

參考資料

相關文章
相關標籤/搜索