本文转载   https://walterlv.github.io/dotnet/2017/09/22/dotnet-version.html ,感谢  吕毅 (包含链接: https://walterlv.github.io )

当我们编译程序目标框架选为 .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. 为什么我们基于 .Net Framework 4.7 开发的程序运行时版本是 4.0?
  2. 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;
  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、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 这三个版本中的一个。

解决一开始的疑问

于是,本文一开始的疑问就全部明晰了:

  1. 不管是 .Net Framework 4.5 的还是 4.7 的那两个程序,都是靠 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.7,但 .Net Framework 基础库并没有安装 4.7 版本,则运行时会提示需要安装 .Net Framework 4.7;
    • 这个提示是 4.0 版的 CLR 弹出的,是根据 supportedRuntime 中指定的 sku 值来决定的

参考资料


本文会经常更新,请阅读原文: https://walterlv.github.io/dotnet/2017/09/22/dotnet-version.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

.Net Framework 4.x 程序到底运行在哪个 CLR 版本之上(ZT)的更多相关文章

  1. .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上

    转帖:https://blog.csdn.net/WPwalter/article/details/78067293 另参考:https://www.cnblogs.com/worksguo/arch ...

  2. Web程序的运行原理及流程(一)

    自己做Web程序的开发也有两年多了 从最开始跟风学框架  到第一用上框架的欣喜若狂 我相信每个程序员都是这样过来的 在大学学习一门语言 学会后往往很想做一个实际的项目出来  我当时第一次做WEB项目看 ...

  3. winform .net2.0的程序如何运行于.net 4.x

    约束 最近有一个winform项目,要求: (1)程序能够运行在winxp, win7, win8, win10中 (2)安装尽可能简单,尽量不要安装.net framework.即使要安装也要尽可以 ...

  4. 更为复杂C程序的运行时结构

    运行环境 win 10 企业版 1809 17763.194,MinGW V3.14 32位,Bundled V3.13.2,Bundled GDB V8.2. 在C语言中,栈的方向是从高地址向低地址 ...

  5. ASP.NET程序也能像WinForm程序一样运行[转载]

    阅读目录 开始 操作方式 支持的ASP.NET程序类别 它也是个HTTP服务器 支持远程机器访问 不受限于Windows防火墙 尊重每个人的操作习惯 内置多标签浏览器支持 启动参数及配置文件 支持 . ...

  6. 谈谈 Python 程序的运行原理

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,谈谈 Python 程序的运行原理 这篇文章准确说是『Python 源码剖析』的 ...

  7. Windows 上的应用程序在运行期间可以给自己改名(可以做 OTA 自我更新)

    原文:Windows 上的应用程序在运行期间可以给自己改名(可以做 OTA 自我更新) 程序如何自己更新自己呢?你可能会想到启动一个新的程序或者脚本来更新自己.然而 Windows 操作系统允许一个应 ...

  8. Hadoop_20_MapReduce程序的运行模式

    1.MapReduce程序的运行模式 1. Windows中运行MapReduce程序 (1)mapreduce程序是被提交给LocalJobRunner在本地以单进程的形式运行 (2)而处理的数据及 ...

  9. C#[Win32&WinCE&WM]应用程序只能运行一个实例:MutexHelper

    前言 在开发应用程序时,通常只让程序运行一个实例.所以,就要判断程序是否已经运行. 下面是我自己在项目中使用到,封装好的帮助类.有 普通的 C# 应用程序 和 Windows CE 和 Windows ...

随机推荐

  1. [程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)

    题目链接 https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&t ...

  2. [ArcGIS]ArcGIS Server环境搭建,发布服务,以及使用ArcGIS API for JavaScript

    环境搭建 安装Web服务器 IIS 控制面板-程序-程序和功能-启用或关闭Windows功能,勾选以下 安装VisualStudio,选择包括ASP.NET模块 安装ArcGIS服务器 ArcGIS ...

  3. [转]Cloudera Manager和CDH5.8离线安装

    https://blog.csdn.net/zzq900503/article/details/52982828 https://www.cnblogs.com/felixzh/p/9082344.h ...

  4. .Net圈子里的一些看法

    金三银四招聘季,不一定一定要跳巢,但是出去看看行情还是有必要的,所以就有这篇随笔. 首先,这里说的.Net圈子是只两个方面 第一,技术人才,属于人的圈子 第二,技术本身,技术的圈子,也就是技术所涵盖的 ...

  5. vue slot 复用

    话不投机半句多,直接上代码 有3步 第一步:创建渲染slot的组件 重要 第二步:为slot添加父组件数据(props) 重要 第三步:使用 第一步:创建渲染slot的组件 首选创建一个单文件组价,由 ...

  6. BP算法的矩阵推导

    目录 1. 需要的微积分知识 1.1 导数 1.2 求导的链式法则 2. 梯度下降法 2.1 梯度 2.2 梯度算法的解释 3.误差反向传播算法 3.1 理论推导 3.1.1 符号说明 3.1.2 推 ...

  7. Linux关闭防火墙命令

    下面是red hat/CentOs7关闭防火墙的命令! 1:查看防火状态 systemctl status firewalld service  iptables status 2:暂时关闭防火墙 s ...

  8. 上传文件,经过Zuul,中文文件名乱码

    问题描述: 在学习<SpingCloud与Docker微服务架构实战>8.7节 使用Zuul上传文件,测试通过Zuul上传中文文件时出现,文件名.目录名或卷标语法不正确异常:但是直接通过上 ...

  9. 如何创建并初始化程序集里List类型的反射

    参考网址:http://stackoverflow.com/questions/315231/using-reflection-to-set-a-property-with-a-type-of-lis ...

  10. easyui-combobox的option选项为true与false时的问题

    如题,我们使用easyui-combobox,当我们的选择项为true与false时,即选择是否,后台返回一个boolean类型的变量,那么这时候,通过form表单进行反显会出现这样的问题:表单里ea ...