当前位置: 首页 > news >正文

.NET/C# 检测电脑上安装的 .NET Framework 的版本

如果你希望知道某台计算机上安装了哪些版本的 .NET Framework,那么正好本文可以帮助你解决问题。


本文内容

    • 如何找到已安装的 .NET Framework
    • 注册表位置和含义
    • 读取注册表

如何找到已安装的 .NET Framework

有的电脑的 .NET Framework 是自带的,有的是操作系统自带的。这样,你就不能通过控制面板的“卸载程序”去找到到底安装了哪个版本的 .NET Framework 了。

关于各个版本 Windows 10 上自带的 .NET Framework 版本,可以阅读 各个版本 Windows 10 系统中自带的 .NET Framework 版本 - walterlv。

而如果通过代码 Environment.Version 来获取 .NET 版本,实际上获取的是 CLR 的版本,详见 使用 PowerShell 获取 CLR 版本号 - walterlv。

这些版本号是不同的,详见 .NET Framework 4.x 程序到底运行在哪个 CLR 版本之上 - walterlv。

那么如何获取已安装的 .NET Framework 的版本呢?最靠谱的方法竟然是通过读取注册表。

注册表位置和含义

读取位置在这里:

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\2052

注册表位置

而唯一准确能够判定 .NET Framework 版本的,只有里面的 Release 值。但可惜的是,这个值并不能直接看出来到底是 4.5 还是 4.8。我们需要有一张对应表。

我把它整理成了字典和注释,这样会比较容易理解每个编号对应的 .NET Framework 版本代号。

/// <summary>
/// 获取 .NET Framework 4.5 及以上版本的发行号与版本名称的对应关系。
/// 4.5 及以下版本没有这样的对应关系。
/// </summary>
private static readonly Dictionary<int, string> ReleaseToNameDictionary = new Dictionary<int, string>
{
    // .NET Framework 4.5
    { 378389, "4.5" },
    // .NET Framework 4.5.1(Windows 8.1 或 Windows Server 2012 R2 自带)
    { 378675, "4.5.1" },
    // .NET Framework 4.5.1(其他系统安装)
    { 378758, "4.5.1" },
    // .NET Framework 4.5.2
    { 379893, "4.5.2" },
    // .NET Framework 4.6(Windows 10 第一个版本 1507 自带)
    { 393295, "4.6" },
    // .NET Framework 4.6(其他系统安装)
    { 393297, "4.6" },
    // .NET Framework 4.6.1(Windows 10 十一月更新 1511 自带)
    { 394254, "4.6.1" },
    // .NET Framework 4.6.1(其他系统安装)
    { 394271, "4.6.1" },
    // .NET Framework 4.6.2(Windows 10 一周年更新 1607 和 Windows Server 2016 自带)
    { 394802, "4.6.2" },
    // .NET Framework 4.6.2(其他系统安装)
    { 394806, "4.6.2" },
    // .NET Framework 4.7(Windows 10 创造者更新 1703 自带)
    { 460798, "4.7" },
    // .NET Framework 4.7(其他系统安装)
    { 460805, "4.7" },
    // .NET Framework 4.7.1(Windows 10 秋季创造者更新 1709 和 Windows Server 1709 自带)
    { 461308, "4.7.1" },
    // .NET Framework 4.7.1(其他系统安装)
    { 461310, "4.7.1" },
    // .NET Framework 4.7.2(Windows 10 2018年四月更新 1803 和 Windows Server 1803 自带)
    { 461808, "4.7.2" },
    // .NET Framework 4.7.2(其他系统安装)
    { 461814, "4.7.2" },
    // .NET Framework 4.8(Windows 10 2019年五月更新 1903 自带)
    { 528040, "4.8" },
    // .NET Framework 4.8(其他系统安装)
    { 528049, "4.8" },
};

另外,还有一些值也是有意义的(只是不那么精确):

  • 主版本
    • 也就是可以共存的版本,比如 v3.5 系列和 v4 系列就是可以共存的,它们分别是就地更新的保持兼容的版本
  • 发行版本名称
    • 完整版 Full 和精简版 Client
  • 版本号
    • 比如 3.5.30729.4926 或者 4.7.02556
  • 服务包版本
    • 古时候的微软喜欢用 SP1 SP2 来命名同一个版本的多次更新,这也就是那个年代的产物

它们分别在注册表的这些位置:

  • 主版本
    • 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP 里项的名称
  • 发行版本名称
    • 以上项里子项的名称
  • 版本号
    • 以上项里的 Version
  • 服务包版本
    • 以上项里的 SP

读取注册表

在上面已经梳理了读取注册表的位置之后,相信你可以很容易写出读取已安装 .NET Framework 版本的代码出来。

我已经将其做成了 NuGet 源代码包(使用 SourceYard 打包),你可以安装 NuGet 包来获得读取已安装 .NET Framework 版本的功能:

  • NuGet Gallery - Walterlv.Environment.Source

或者在 GitHub 查看源代码:

  • Walterlv.Packages/NdpInfo.cs at master · walterlv/Walterlv.Packages

只有一个类型——NdpInfo

使用方法有两种。

第一种,获取当前计算机上所有已经安装的 .NET Framework 版本:

var allVersions = await NdpInfo.ReadFromRegistryAsync();

执行完成之后看看得到的字典 allVersions 如下:

已安装的全部 .NET Framework

字典里 Key 是不能共存的主版本,Value 是这个主版本里当前已经安装的具体版本信息。

如果直接使用 ToString(),是可以生成我们平时经常在各大文档或者社区使用的 .NET Framework 的名称。

第二种,获取当前已安装的最新的 .NET Framework 版本名称:

var currentVersion = NdpInfo.GetCurrentVersionName();

这可以直接获取到一个字符串,比如 .NET Framework 4.8。对于只是简单获取一下已安装名称而不用做更多处理的程序来说会比较方便。


我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • Windows 系统上用 .NET/C# 查找所有窗口,并获得窗口的标题、位置、尺寸、最小化、可见性等各种状态
  • 直击本质:WPF 框架是如何实现模态窗口的
  • 什么是模态窗口?本文带你了解模态窗口的本质
  • 使用 .editorconfig 配置 .NET/C# 项目的代码分析规则的严重程度
  • 如何在 .NET 项目中开启不安全代码(以便启用 unsafe fixed 等关键字)
  • WPF 高性能位图渲染 WriteableBitmap 及其高性能用法示例
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • 使用 Direct3D11 的 OpenSharedResource 方法渲染来自其他进程/设备的共享资源(SharedHandle)
  • 将 Direct3D11 在 GPU 中的纹理(Texture2D)导出到内存(Map)或导出成图片文件
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • C#/.NET 当我们在写事件 += 和 -= 的时候,方法是如何转换成事件处理器的
  • 清理 git 仓库太繁琐?试试 bfg!删除敏感信息删除大文件一句命令搞定(比官方文档还详细的使用说明)
  • 可集成到文件管理器,一句 PowerShell 脚本发布某个版本的所有 NuGet 包
  • Windows 系统的默认字体是什么?应用的默认字体是什么?
  • C# 8.0 的可空引用类型,不止是加个问号哦!你还有很多种不同的可空玩法
  • Angular2开发踩坑系列-生产环境编译
  • ECMAScript入门(七)--Module语法
  • ES6系列(二)变量的解构赋值
  • overflow: hidden IE7无效
  • Python学习笔记 字符串拼接
  • Redis 中的布隆过滤器
  • tab.js分享及浏览器兼容性问题汇总
  • uva 10370 Above Average
  • 给新手的新浪微博 SDK 集成教程【一】
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 使用Gradle第一次构建Java程序
  • 网络应用优化——时延与带宽
  • 小程序 setData 学问多
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • 仓管云——企业云erp功能有哪些?
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • !$boo在php中什么意思,php前戏
  • ###C语言程序设计-----C语言学习(6)#
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (14)Hive调优——合并小文件
  • (a /b)*c的值
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (JS基础)String 类型
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)http-server应用
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • **PHP二维数组遍历时同时赋值
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net core 6 集成和使用 mongodb
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • [ CTF ] WriteUp- 2022年第三届“网鼎杯”网络安全大赛(白虎组)
  • [2010-8-30]
  • [20180224]expdp query 写法问题.txt