遇见最美Windows 11之现代Windows桌面应用开发 探索.Net framework和CLR版本关系

背景

托管公共语言运行时(CLR)的所有应用程序都必须启动(或激活)CLR,才能运行托管代码。通常,.NET Framework应用在生成它的CLR版本上运行,但你可以使用应用程序配置文件(有时称为app.config文件)来更改桌面应用程序的此行为。

如果CLR激活系统无法加载应用程序所需运行时的正确版本,它将向用户显示一条错误消息,通知他们,他们的计算机未正确配置,无法运行该应用程序,并为他们提供机会来修复该问题。在此情况下通常会显示以下错误消息。用户可以选择“是”以转到Microsoft网站,从中为应用程序下载正确的.NETFramework版本。

image

若要解决根本问题并提供最佳用户体验(更少错误消息),建议执行以下操作:

  • 对于.NET Framework 3.5(和更低版本)应用程序:将应用程序配置为支持.NET Framework 4或更高版本
  • 对于.NET Framework 4应用程序:安装.NET Framework 4可再发行组件包,作为应用程序安装的一部分

Windows 8/10/11行为和UI

CLR激活系统在Windows 8/10/11上提供与在其他版本Windows操作系统上一样的行为和UI,除非加载CLR 2.0时遇到问题。Windows 8包括使用CLR 4.5的.NET Framework 4.5。但是,Windows 8不包括.NET Framework 2.0、3.0或3.5,它们都使用CLR 2.0。结果,依赖于CLR 2.0的应用程序默认情况下在Windows 8上不运行。相反,它们将显示下面的对话框,使用户能够安装.NET Framework 3.5。用户还可在“控制面板”中启用.NET Framework 3.5。

image

安装.NET Framework 3.5后,用户可以在其Windows8计算机上运行依赖于.NET Framework 2.0、3.0或3.5的应用程序。他们还可以运行.NET Framework 1.0和1.1应用程序,前提是这些应用程序未显式配置为仅在.NET Framework 1.0或1.1版上运行。

什么是通用语言运行库CLR

image

通用语言执行平台(Common Language Runtime,简称CLR)是微软为.NET的虚拟机所选用的名称。它是微软对通用语言架构(CLI)的实现版本,它定义了一个代码执行的环境。CLR执行一种称为通用中间语言(Common Intermediate Language,简称CIL)的字节码,这个是微软的通用中间语言实现版本。

CLR的主要功能如下

  • 基类库支持(Base Class Library Support)
  • 内存管理(Memory Management)
  • 线程管理(Thread Management)
  • 垃圾回收(Garbage Collection)
  • 安全性(Security)
  • 类型检查(Type Checker)
  • 异常管理(Exception Manager)
  • 调试管理(Debug Engine)
  • 中间码(MSIL)到机器代码(Native)编译
  • 类别装载(Class Loader)

开发人员使用高级编程语言撰写程序。接下来编译器将代码编译成微软的中继语言(MSIL)。执行的时候CLR会将MSIL码转换为操作系统的原生码(Native Code)。CLR内置有"即时编译(Just-in-time compilation)"编译器。

检测已安装.Net framework版本

检测工具介绍

用户可在他们的计算机上安装和运行.NET Framework的多个版本。当你开发或部署应用时,你可能需要知道用户的计算机上安装了哪些.NET Framework版本。注册表包含计算机上安装的.NET Framework版本列表。

.NET Framework由两个采用不同版本的主要组件构成:

  • 一组程序集,它们是为应用提供功能的类型与资源的集合。.NET Framework和程序集使用相同的版本号。例如,.NET Framework版本包括4.5、4.6.1和4.7.2。
  • 公共语言运行时(CLR),可管理并执行应用代码。单个CLR版本通常可支持多个.NET Framework版本。例如,CLR版本4.0.30319.xxxxx(其中xxxxx小于42000)支持.NET Framework版本4到4.5.2。大于或等于4.0.30319.42000的CLR版本支持从.NET Framework 4.6开始的.NET Framework版本。

可使用社区维护的工具帮助检测安装了哪些.NET Framework版本:

使用DotNetVersions检测

解压后,直接运行DotNetVersions.exe程序即可。

image

它会通过终端命令行弹出界面来显示出打印结果,我们便可知道当前系统中已经安装哪些版本了。

image

使用DotNetVersionLister检测

通过命令行可以直接安装它。

Install-Module -Name DotNetVersionLister -Scope CurrentUser #-Force

image

安装后,调用命令行来使用它。

Get-STDotNetVersion

image

或者检测远程计算机的版本

Get-STDotNetVersion -ComputerName $RemoteServerName

通过注册表位置来确认已安装版本

通过Win + R组合来运行regedit,可进入注册表编辑器,输入如下路径,可以查看到所有.Net framework版本的注册表信息。

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP

image

通过v4\Full路径下子项中Release的值确定已安装的版本,注册表值和.Net framework版本对应关系如下:

.NET Framework 版本 Release的值
.NET Framework 4.5 所有Windows 操作系统:378389
.NET Framework 4.5.1 在Windows 8.1和Windows Server2012R2上:378675
在所有其他Windows 操作系统上:378758
.NET Framework 4.5.2 所有Windows 操作系统:379893
.NET Framework 4.6 在Windows 10上:393295
在所有其他Windows 操作系统上:393297
.NET Framework 4.6.1 在Windows 1011月更新系统上:394254
在所有其他Windows 操作系统(包括Windows 10)上:394271
.NET Framework 4.6.2 在Windows 10周年更新和Windows Server 2016上:394802
在所有其他Windows 操作系统(包括其他Windows 10操作系统)上:394806
.NET Framework 4.7 在Windows 10创意者更新上:460798
在所有其他Windows 操作系统(包括其他Windows 10操作系统)上:460805
.NET Framework 4.7.1 在Windows 10 Fall Creators Update和Windows Server版本1709上:461308
在所有其他Windows 操作系统(包括其他Windows 10操作系统)上:461310
.NET Framework 4.7.2 在Windows 10 2018年4月更新和Windows Server版本1803上:461808
在除Windows 102018年4月更新和Windows Server版本1803之外的所有Windows 操作系统上:461814
.NET Framework 4.8 在Windows 10 2019年5月更新和Windows 102019年11月更新上:528040
在Windows 10 2020年5月更新、Windows 10 2020年10月更新和Windows 102021年5月更新上:528372
在Windows 11和Windows Server 2022上:528449
在所有其他Windows 操作系统(包括其他Windows 10操作系统)上:528049

.Net framework版本与CLR的关系

.NET框架是微软公司继Windows DNA之后的新开发平台。.NET框架是以一种采用系统虚拟机运行的编程平台,以通用语言运行库(Common Language Runtime)为基础,支持多种语言(C#、F#、VB.NET、C++、Python等)的开发。

image

2014年11月12日,微软宣布将完全开放.NET框架的源代码,并提供给Linux和macOS使用。

.Net framework版本历史

版本 公共语言执行时 发布时间 随同分发于Visual Studio 预安装于Windows 包含之前版本
客户端版 服务器版
1.0 1.0 2002年2月13日 .NET 不适用 不适用 不适用
1.1 1.1 2003年4月24日 .NET 2003 不适用 2003
2.0 2.0 2005年11月7日 2005 不适用 2003 R2
3.0 2006年11月6日 不适用 Vista 不适用 2.0
3.5 3.5 2007年11月19日 2008 不适用 不适用 3.0 SP1 (2.0 SP1)
3.5.1 2008年2月4日 不适用 不适用 2008
3.5 SP1 2008年8月11日 2008 SP1 不适用 不适用 3.0 SP2 (2.0 SP2)
3.5.1 SP1 2009年7月22日 不适用 7 2008 R2
4 4.0 4.0 2010年4月12日 2010 不适用 不适用 不适用(置位更新)
4.5 2012年8月15日 2012 8 2012
4.5.1 2013年10月17日 2013 8.1 2012 R2
4.5.2 2014年5月5日 不适用 不适用 不适用
4.6 2015年7月20日 2015 10 不适用
4.6.1 2015年11月30日 2015 Update 1 10 v1511 不适用
4.6.2 2016年8月2日 不适用 10 v1607 2016
4.7 2017年4月5日 2017 v15.3 10 v1703 不适用
4.7.1 2017年10月17日 2017 v15.5 10 v1709 v1709
4.7.2 2018年4月30日 2019 10 v1803 v1803
4.8 2019年4月18日 不适用 10 v1909 v1909

针对.NET Framework的可再发行组件包和语言包

勤学实践

https://github.com/TaylorShi/HelloDesktopAppConfig

创建解决方案HelloDesktopAppConfig

dotnet new sln -o HelloDesktopAppConfig
cd .\HelloDesktopAppConfig\
explorer.exe .

image

创建.Net framework项目demoForNetFramework2

image

选择C#语言-Windows平台-桌面类型,选中Windows窗体应用模板,创建名为demoForNetFramework2的项目。

image

image

这里框架选定:.Net framework 2.0

image

创建.Net framework项目demoForNetFramework3

选择C#语言-Windows平台-桌面类型,选中Windows窗体应用模板,创建名为demoForNetFramework3的项目。

image

这里框架选定:.Net framework 3.5

创建.Net framework项目demoForNetFramework4

选择C#语言-Windows平台-桌面类型,选中Windows窗体应用模板,创建名为demoForNetFramework4的项目。

image

这里框架选定:.Net framework 4

创建.Net framework项目demoForNetFramework4.5

选择C#语言-Windows平台-桌面类型,选中Windows窗体应用模板,创建名为demoForNetFramework45的项目。

image

这里框架选定:.Net framework 4.5

image

我们发现,在demoForNetFramework45项目中会比之前多出来一个App.config配置文件。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

创建.Net framework项目demoForNetFramework4.8

选择C#语言-Windows平台-桌面类型,选中Windows窗体应用模板,创建名为demoForNetFramework48的项目。

image

这里框架选定:.Net framework 4.8

我们发现,在demoForNetFramework48项目中会比之前多出来一个App.config配置文件。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
    </startup>
</configuration>

查看已有的应用配置文件

从上诉创建结果来看,从.Net framework 4.5的项目模板开始,Visual Studio就已经内置并在创建项目的时候,添加了应用配置文件App.config,虽然这里它叫App.config,但是你会发现编译生成后的对应的文件不叫这个,而是和exe同名的一个config文件,比如编译后得到的程序是demoForNetFramework48.exe,那么得到的配置文件实际上最终名称和它一一对应,叫做demoForNetFramework48.exe.config,我们查看Bin下面的文件,这印证了这个说法。

image

image

补充新建应用配置文件

对于较老版本的.Net framework项目而言,创建之后并没有携带应用配置文件,那么我们可以自己来创建一个,在项目上右键-添加-新建项

image

在左侧切换到常规-应用程序配置文件,点击添加即可。

image

image

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>

默认得到的是个几乎空白没有意义的XML文件,这时候需要我们自己根据需要填充。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="version"/>
  </startup>
</configuration>

其中Version版本字段,指定与你的应用程序支持的.NET Framework版本匹配的CLR版本。使用以下字符串:

  • .NET Framework 1.0:v1.0.3705
  • .NET Framework 1.1:v1.1.4322
  • .NET Framework 2.0、3.0和3.5:v2.0.50727
  • .NET Framework 4及更高版本:v4.0

并且我们可以通过多组SupportedRuntime节点来指定对多个.NET Framework版本的支持。

注意书写时需要按优先级顺序写出,优先级高的放置在前面。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0"/>
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

关于SupportedRuntime的组合与安装了不同版本.Net framework运行时计算机的对应情况

App.config文件设置 在安装了3.5版的计算机上 在安装了版本3.5和4或更高版本的计算机上 在安装了版本4或更高版本的计算机上
None 在3.5上运行 在3.5上运行 显示提示用户安装正确版本的错误消息
<supportedRuntimeversion="v2.0.50727"/> 在3.5上运行 在3.5上运行 显示提示用户安装正确版本的错误消息
<supportedRuntimeversion="v2.0.50727"/><supportedRuntimeversion="v4.0"/> 在3.5上运行 在3.5上运行 在4或更高版本上运行
<supportedRuntimeversion="v4.0"/><supportedRuntimeversion="v2.0.50727"/> 在3.5上运行 在4或更高版本上运行 在4或更高版本上运行
<supportedRuntimeversion="v4.0"/> 显示提示用户安装正确版本的错误消息 在4或更高版本上运行 在4或更高版本上运行

允许混合模式程序集加载到更高版本.Net framework

虽然我们可以通过SupportedRuntime的组合来实现程序对已安装.Net framework版本的灵活选择,但是默认情况下,想要在仅安装.Net framework v4.0及其以上版本环境中继续使用.Net 3.5或者.Net 2.0的程序集是不被允许的。

如需允许.Net framework v4.0及其以上版本运行较低.Net framework版本(如v2.0、v3.5)的程序集,那么可以通过设置Startup节点的useLegacyV2RuntimeActivationPolicy属性值为true,来实现运行的兼容,这意味着在仅有v4.0+的计算机上仍然可以支持较低版本应用程序的运行。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0"/>
        <supportedRuntime version="v2.0.50727"/>
    </startup>
</configuration>

这对由较低.Net framework版本构建的.Net桌面应用程序实现向前兼容运行非常有用。

总结来说:SupportedRuntime节点组,主要是帮助程序在同时安装了多个.Net framework(比如3.5&4.0)的版本的计算机环境中去择选更优的运行时版本,而UseLegacyV2RuntimeActivationPolicy设置成true,可以让较低.Net framework(比如2.0/3.5)版本构建的桌面程序在仅安装了较高.Net framework(比如4.0/4.5/4.8)版本的计算机环境中兼容运行。

参考

原文地址:https://www.cnblogs.com/taylorshi/p/15768620.html