1. 程式人生 > >.Net Framework 4.x 程式到底執行在哪個 CLR 版本之上

.Net Framework 4.x 程式到底執行在哪個 CLR 版本之上

轉帖:https://blog.csdn.net/WPwalter/article/details/78067293

另參考:https://www.cnblogs.com/worksguo/archive/2010/02/10/1666939.html

當我們編譯程式目標框架選為 .Net Framework 4.5/4.6/4.7 時,CLR 執行時是如何判斷我們究竟應該用哪一個 .Net Framework 呢?.Net Framework 的版本到底由哪些部分組成?我們編譯 .Net Framework 時選擇的版本到底決定了什麼?

讓我對這個問題產生興趣的原因是:
- 我將程式編譯的目標框架選為 .Net Framework 4.7;在一臺安裝了 .Net Framework 4.6 的電腦上提示缺少 .Net Framework 4.7;刪除了隨編譯一起生成的 app.config 檔案後程序能夠正常執行。
- 另一個程式,我明明將程式編譯的目標框架選為 .Net Framework 4.5,但在一臺沒有安裝任何額外 .Net Framework 的 Windows 7 的電腦上提示缺少的是 .Net Framework 4.0。

這裡的疑點在於為什麼以上兩種看似類似的情況,提示的框架版本卻不同。其中的 app.config 檔案成為了調查此問題的突破口。
配置支援的執行時

觀察程式附帶的 app.config 檔案,我們發現支援的執行時版本是 v4.0,sku 版本是 4.7。

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

    1
    2
    3
    4
    5

疑點:
1. 為什麼我們基於 .Net Framework 4.7 開發的程式執行時版本是 4.0?
1. sku 是什麼?

微軟的官方文件給了我們解答:supportedRuntime Element。

    version:用於指定此應用程式支援的公共語言執行時(CLR)的版本。
    sku:stock-keeping unit(官方中文為“庫存單位”,然而依然不懂這個詞的意思),用於指定此應用程式支援的 .Net Framework 發行版本。

version 的值可取:
.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.7     “v4.0”

sku 的值可取:
.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”

於是我們發現,其實無論我們將程式的目標框架選為 .Net Framework 的哪一個 4.x 版本,CLR 執行時都是用 v4.0 表示的。微軟的描述是:

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

其實看到這裡我們就能有一個看似不錯的解釋:
1. 無論我們選擇的目標框架是 .Net Framework 4.x 的哪一個版本,用於指定 CLR 執行時版本的 version 值都是 v4.0;
1. 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、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.2、4.6、4.6.1、4.6.2 和 4.7 是對 .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.1、4.5.2、4.6 這三個版本中的一個。

每一個不同的 .Net Framework 基礎庫有自己單獨的資料夾
解決一開始的疑問

於是,本文一開始的疑問就全部明晰了:
1. 不管是 .Net Framework 4.5 的還是 4.7 的那兩個程式,都是靠 4.0 版本的公共語言執行時(CLR)執行起來的;
1. 如果沒有安裝 4.0 版本的 CLR,則會彈出提示需要安裝 .Net Framework 4.0 版本才能執行,而不管我們的程式目標框架是 .Net Framework 4.x 的哪一個版本;
- 雖然說文案說的是 .Net Framework,但其實需要的是 CLR
1. 如果已經安裝有 4.0 版本的 CLR(可能隨 .Net Framework 4.5/4.6 安裝),我們程式的目標框架是 .Net Framework 4.7,但 .Net Framework 基礎庫並沒有安裝 4.7 版本,則執行時會提示需要安裝 .Net Framework 4.7;
- 這個提示是 4.0 版的 CLR 彈出的,是根據 supportedRuntime 中指定的 sku 值來決定的
參考資料

    supportedRuntime Element - Microsoft Docs
    .NET Framework Versions and Dependencies - Microsoft Docs
    .NET 4.5 is an in-place replacement for .NET 4.0 - Rick Strahl’s Web Log
    app config - What does “SKU” (attribute) mean in C#? - Stack Overflow
    .net - What happens if I remove the auto added supportedRuntime element? - Stack Overflow
---------------------
作者:walter lv
來源:CSDN
原文:https://blog.csdn.net/WPwalter/article/details/78067293
版權宣告:本文為博主原創文章,轉載請附上博文連結!