确定安装了哪些 NET Framework 版本
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了确定安装了哪些 NET Framework 版本相关的知识,希望对你有一定的参考价值。
以下内容均出自Vagrant作者(Mitchell Hashimoto)与Docker作者(Solomon Hykes)在stackoverflow上面一个问题讨论。在这个问题中,双方阐述了vagrant和docker的特点和使用范围,对于深入理解vagrant和docker很有意义,因此笔者翻译出来,以供大家讨论学习。Mitchell作为vagrant的作者,其在DevOps的世界里面沉浸多年,接触了很多类似docker的虚拟化软件。他目前接触了很多使用vagrant和docker的场景,所以看到了两者是如何相互搭配发生作用的。
他认为如果单单是开发人员一个人单独使用主机,使用docker可以简化很多事情,这种场景下使用docker和vagrant都没有什么区别。所以他更多的讨论了一些复杂场景,在这些复杂场景中,docker和vagrant就有一些区别了。
以下是他原文:
不分场景而直接比对vagrant和docker是不恰当的!在一些简单场景中,它们两款产品作用是重复的,但在更多场景中,它们两款产品无法相互替 代。事实上,vagrant抽象度比docker更高,因此直接用vagrant同docker相比较是不恰当的。而把vagrant同 Boot2Docker(一款运行docker最小的内核) 进行比较似乎更加恰当。
vagrant为了支持开发,在启动虚拟机环境时启动了很多的应用和服务。vagrant可以在VirtualBox, VMware上面运行(docker无法执行)。vagrant也可以在AWS, OpenStack这些云环境中运行。即便你使用了docker的容器,vagrant同样也没问题。vagrant可以自动install, pull down, build, run Docker containers。
比如在vagrant V1.6版本中,vagrant集成了docker-based development environments,因此Vagrant可以在windows,mac和linux上面提供docker服务。
vagrant没有想替代docker的想法,相反它还包含了docker的一些特性。
如果我们从逻辑层面来比较vagrant和docker的话,那么:
1、docker只能执行docker所定义的容器。
2、docker缺乏灵活的隔离方案(docker只能运行在Linux主机环境中)。
如果我们从Production和CI层面来比较,那么docker就无法与vagrant相比了:Vagrant没有上面的约束条件,而docker必须依赖它们。
如果你的项目必须使用Docker的容器,同时只能部署在Linux主机中。这个时候Docker的确是一个不错的选择。除此之外,我就看不到使用docker的优势了,相反你还浪费了vagrant很多的优点:
vagrant可以支持多种虚拟环境,例如 VirtualBox, VMware, AWS, OpenStack等等。无论你使用何种虚拟环境,vagrant都可以顺利执行起来。如果你使用了Docker,也可以在vagrant中顺利安装docker。
vagrant可以降低项目复杂度。或者换个说法:你只需要考虑如何执行你的项目就可以,而不论这个项目是用的docker还是什么别的。在未来,如果出现了docker的竞争者,那么vagrant也可以顺利执行它。
vagrant可以运行在多个主机环境中,windows(XP以上),MAC(10.5以上),Linux(2.6内核版本以上)。如果你使用了docker,那么vagrant也可以在上面三种操作系统之上运行你的docker。
vagrant 可以更好的配置网络和文件共享。比如:vagrant可以给一个VM配置静态IP和端口数据转发。不论你使用的VirtualBox还是 VMware,vagrant都可以很好的完成配置。对于文件共享来说,vagrant提供了多种文件挂载方案供你考虑。如果你使用了docker,那么 这些事情就都需要你亲自动手来做了。
vagrant 1.6中集成了docker-based development environments。所以在MAC和Windows环境中,vagrant会自动启动一个虚拟机来执行docker,这样就达到了docker的跨平台化。而背后例如网络,文件等等操作都是vagrant默默完成的。
下面两点是我听到docker可以替代vagrant的声音:
"Docker 需要移动的数据很少"的确,Docker有这个特点(应该指的是Docker采用的UFS,导致docker每次变动所需的数据很少--笔者猜测)。但是 当你在每个项目都使用docker,或者在每个项目的现在,将来都使用docker时,你就会发现docker所产生的数据并不少。而如果你使用 vagrant,那么只需要移动一次就可以完成。(原文:"It is less moving parts" - Yes, it can be, if you use Docker exclusively for every project. Even then, it is sacrificing flexibility for Docker lock-in. If you ever decide to not use Docker for any project, past, present, or future, then you\'ll have more moving parts. If you had used Vagrant, you have that one moving part that supports the rest).
"Docker启动非常快",当使用docker启动容器时,它比其他虚拟机启动的都快。但是我要说的是,目前从产品化角度分析所有vagrant主机基本都是启动一次,然后不再停机。如果从快速部署开发环境来说,docker这个特性真的是非常好。
所以,我们现在可以得知vagrant和docker是有很大区别的,直接比较这两个是不正确的。对于开发环境来说,vagrant是一种更为抽象,更为通用的解决方案。Docker所能提供的场景只是vagrant所支持的特殊场景之一。
在一些极端案例场景下,docker完全可以替代vagrant。但在更多的场景下,这是错误的。同时vagrant也不会封锁你使用docker。
针对Mitchell的这些解释,Hykes写出了下述的论点:
如果你仅仅是想管理虚拟机,那么你应该使用vagrant。如果你想快速开发和部署应用,那么应该使用docker。
vagrant是一款管理虚拟机的工具,而docker是一款通过将应用打包到轻量级容器,而实现构建和部署的工具。两者适用范围不同。一个容器就是一个包含了应用执行所依赖的数据(包括lib,配置文件等等)。它可以保证应用在一个可重复的环境中随时执行。
有了这个容器,就可以很简单的构建你的容器也可以随时随地的进行部署。
Docker只能在Linux上面执行是一个很大的误区!事实上,Docker可以在MAC和Windows上面安装。如果你在MAC上面安装 Docker,那么会有一个大概25MB的精简Linux VM来充当MAC和docker直接的交流者。一旦Docker安装完成后,就可以使用同样的命令进行操作了。这样,世界一下就美好了:你通过轻量级的容 器可以更好的测试和开发你的应用,并且很容易的将这些应用进行分发(比如通过 https://index.docker.io)。而你不需要了解如何管理这些虚拟机,而仅仅把虚拟机当做完成事情中的一个环节而已。
理论上,vagrant可以作为docker一个抽象数据层。理由如下:
首 先,vagrant不是对docker更好的抽象。vagrant设计使用来管理虚拟机的,而docker设计是用来管理应用的。这就意味着docker 在设计之初就是为了可以通过多种方式来相互组合应用。在docker中processes, log streams, environment variables ,network links between components是最底层的原型。在vagrant中machines, block devices, and ssh keys是最底层的原型。vagrant工作在系统底层,它同另外一个vagrant容器交互的方式只有把它当做一个可以"boot"和"log into"的机器。因此,你可以在docker上面安装插件后,执行"vagrant up"命令后等待美好的事情发生。
其 次,可锁定的环境参数(the lock-in argument)。""If you use Vagrant as an abstraction, you will not be locked into Docker!"站在管理虚拟机的vagrant角度上面看,这句说没有错:Docker不是另外一个独立的容器。像EC2和VMware一样,我们要避 免创造一个和其它工具相捆绑的东西。Docker对宿主机没有任何要求,它允许你通过轻量级的容器在任意地方进行部署。在你部署应用时,不需要考虑应该部 署到什么环境中。比如说:你可以在其他人提供的主机(很可能上面已经部署了EC2或者vagrant)上面部署应用。
所以最后可以说:Vagrant 适合用来管理虚拟机,而docker适合用来管理应用环境。
CentOS 6/7系列安装Docker http://www.linuxidc.com/Linux/2014-07/104768.htm
Docker的搭建Gitlab CI 全过程详解 http://www.linuxidc.com/Linux/2013-12/93537.htm
Docker安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm
Docker 和一个正常的虚拟机有何区别? http://www.linuxidc.com/Linux/2013-12/93740.htm
在 Docker 中使用 mysql http://www.linuxidc.com/Linux/2014-01/95354.htm
Docker 将改变所有事情 http://www.linuxidc.com/Linux/2013-12/93998.htm
Docker安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm 参考技术A 查看这个目录可以知道安装了哪些版本;
要注意的是 .NET Framework 4.5 是一个针对 .NET Framework 4 的高度兼容的更新。在上面图中.NET Framework 4.5 显示为“v4.0.30319”
如何检测安装了哪些 .NET Framework 版本和服务包?
【中文标题】如何检测安装了哪些 .NET Framework 版本和服务包?【英文标题】:How do I detect what .NET Framework versions and service packs are installed? 【发布时间】:2010-09-16 23:28:36 【问题描述】:here 提出了类似的问题,但它是特定于 .NET 3.5 的。具体来说,我正在寻找以下内容:
-
确定安装了哪些 .NET Framework 版本和服务包的正确方法是什么?
是否有可以使用的注册表项列表?
Framework 版本之间是否存在依赖关系?
【问题讨论】:
这个问题与***.com/questions/198931/…和***.com/questions/182910/…密切相关 是的。我已经知道第一个(这是我在问题中提到的那个)。我不知道另一个。 我对这个问题(包括答案)和所有密切相关的问题完全忽略了SKU values 的存在印象深刻——这甚至区分了 4.5 和 4.5.1。 @springy76,这不解决 SKU 值存在的原因是,为了确定安装了哪些版本的框架,它们不相关。您提到的问题实际上是试图确定是否安装了“.NET 4.0.2”。这里的问题是没有 .NET 4.0.2,它是一个更新 (KB2544514),而不是框架版本或服务包。您可以在 MSDN (msdn.microsoft.com/en-us/library/hh925567(v=vs.110).aspx) 上查看这篇文章,了解有关如何检测安装了哪些更新的更多信息。 这里有Check which version of .net ... 【参考方案1】:注册表是the official way,用于检测是否安装了特定版本的框架。
根据您要查找的框架版本,需要更改哪些注册表项:
框架版本注册表项 -------------------------------------------------- -------------------------------------- 1.0 HKLM\Software\Microsoft\.NETFramework\Policy\v1.0\3705 1.1 HKLM\Software\Microsoft\NET Framework Setup\NDP\v1.1.4322\Install 2.0 HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\Install 3.0 HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\InstallSuccess 3.5 HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.5\Install 4.0 客户端配置文件 HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Client\Install 4.0 完整配置文件 HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Full\Install通常您正在寻找:
"Install"=dword:00000001
.NET 1.0 除外,其中值是字符串 (REG_SZ
) 而不是数字 (REG_DWORD
)。
确定服务包级别遵循类似的模式:
框架版本注册表项 -------------------------------------------------- -------------------------------------- 1.0 HKLM\Software\Microsoft\Active Setup\Installed Components\78705f0d-e8db-4b2d-8193-982bdda15ecd\Version 1.0[1] HKLM\Software\Microsoft\Active Setup\Installed Components\FDC11A6F-17D1-48f9-9EA3-9051954BAA24\Version 1.1 HKLM\Software\Microsoft\NET 框架设置\NDP\v1.1.4322\SP 2.0 HKLM\Software\Microsoft\NET 框架设置\NDP\v2.0.50727\SP 3.0 HKLM\Software\Microsoft\NET 框架设置\NDP\v3.0\SP 3.5 HKLM\Software\Microsoft\NET 框架设置\NDP\v3.5\SP 4.0 客户端配置文件 HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Client\Servicing 4.0 完整配置文件 HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Full\Servicing [1] Windows Media Center 或 Windows XP 平板电脑版如您所见,如果您在 Windows Media Center 或 Windows XP Tablet Edition 上运行,确定 .NET 1.0 的 SP 级别会发生变化。同样,.NET 1.0 使用字符串值,而所有其他版本都使用 DWORD。
对于 .NET 1.0,这两个键的字符串值的格式为 #,#,####,#。最后一个 # 是 Service Pack 级别。
虽然我没有明确要求这样做,但如果您想知道框架的确切版本号,您可以使用以下注册表项:
框架版本注册表项 -------------------------------------------------- -------------------------------------- 1.0 HKLM\Software\Microsoft\Active Setup\Installed Components\78705f0d-e8db-4b2d-8193-982bdda15ecd\Version 1.0[1] HKLM\Software\Microsoft\Active Setup\Installed Components\FDC11A6F-17D1-48f9-9EA3-9051954BAA24\Version 1.1 HKLM\Software\Microsoft\NET 框架设置\NDP\v1.1.4322 2.0[2] HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\Version 2.0[3] HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\Increment 3.0 HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Version 3.5 HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.5\Version 4.0 客户端配置文件 HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Version 4.0 完整配置文件 HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Version [1] Windows Media Center 或 Windows XP 平板电脑版 [2] .NET 2.0 SP1 [3] .NET 2.0 原始版本 (RTM)同样,.NET 1.0 使用字符串值,而所有其他版本都使用 DWORD。
附加说明
对于 .NET 1.0,这两个键的字符串值的格式为 #,#,####,#
。字符串的#,#,####
部分是框架版本。
对于 .NET 1.1,我们使用注册表项本身的名称,它代表版本号。
1234563同样,.NET 3.5 为 .NET 2.0 和 .NET 3.0 添加了附加功能,因此 .NET 2.0、.NET 3.0 和 .NET 3. 都应评估为已安装以正确表示已安装 .NET 3.5。.NET 4.0 安装了新版本的 CLR(CLR 4.0 版),它可以与 CLR 2.0 并行运行。
.NET 4.5 更新
如果安装了 .NET 4.5,注册表中不会有 v4.5
键。相反,您必须检查HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Full
键是否包含名为Release
的值。如果存在此值,则安装 .NET 4.5,否则不安装。更多详情请见here和here。
【讨论】:
这似乎不适用于 Vista x64 下的 .NET 1.1。任何可能的地方都没有 v1.1.x 密钥。想法? .NET 4.0 的密钥不太正确。我看到这些键: HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Client\Install HKLM\Software\Microsoft\NET Framework Setup\NDP\v4\Full\Install v4.0 文件夹只有一个键, (默认),值为 deprecated。 本帖不涉及4.5,4.5即使安装也未在注册表中列出。 伙计,微软没有人想过添加 -version 开关吗? 开个玩笑。我不敢相信这太愚蠢了!【参考方案2】:这是一个 PowerShell 脚本,用于获取已安装的 .NET 框架版本
function Get-KeyPropertyValue($key, $property)
if($key.Property -contains $property)
Get-ItemProperty $key.PSPath -name $property | select -expand $property
function Get-VersionName($key)
$name = Get-KeyPropertyValue $key Version
$sp = Get-KeyPropertyValue $key SP
$install = Get-KeyPropertyValue $key Install
if($sp)
"$($_.PSChildName) $name SP $sp"
else
"$($_.PSChildName) $name"
function Get-FrameworkVersion
dir "hklm:\SOFTWARE\Microsoft\NET Framework Setup\NDP\" |? $_.PSChildName -like "v*" |%
if( $_.Property -contains "Version")
Get-VersionName $_
else
$parent = $_
Get-ChildItem $_.PSPath |%
$versionName = Get-VersionName $_
"$($parent.PSChildName) $versionName"
$v4Directory = "hklm:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"
if(Test-Path $v4Directory)
$v4 = Get-Item $v4Directory
$version = Get-KeyPropertyValue $v4 Release
switch($version)
378389 ".NET Framework 4.5"; break;
378675 ".NET Framework 4.5.1 installed with Windows 8.1 or Windows Server 2012 R2"; break;
378758 ".NET Framework 4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2"; break;
379893 ".NET Framework 4.5.2"; break;
393295, 393297 -contains $_ ".NET Framework 4.6"; break;
394254, 394271 -contains $_ ".NET Framework 4.6.1"; break;
394802, 394806 -contains $_ ".NET Framework 4.6.2"; break;
它是基于 How to: Determine Which .NET Framework Versions Are Installed 编写的。请使用 Get-FrameworkVersion() 函数获取有关已安装的 .NET 框架版本的信息。
【讨论】:
【参考方案3】:我想检测我的系统上是否安装了 .NET 版本 4.5.2,但我没有找到比 ASoft .NET Version Detector 更好的解决方案。
显示不同 .NET 版本的此工具的快照:
【讨论】:
【参考方案4】:在 Windows 7 中(它应该也适用于 Windows 8,但我还没有测试过):
转到命令提示符
进入命令提示符的步骤:
-
点击开始菜单
在搜索框中,输入“cmd”(不带引号)
打开 cmd.exe
在 cmd 中,输入此命令
wmic /namespace:\\root\cimv2 path win32_product where "name like '%%.NET%%'" get version
这提供了最新版本的 NET Framework 安装。
也可以试试Raymond.cc Utilties。
【讨论】:
在cmd
中运行该行会得到ERROR: Description = Invalid namespace
。
我也收到ERROR: Description = Invalid namespace
这个命令给我错误! (从 Windows 7 终端执行)
感谢 MEMark、Peter、Smrita 的通知。【参考方案5】:
有一个 GUI 工具可用,ASoft .NET Version Detector,它一直被证明是高度可靠的。它可以通过在命令行中指定 XML 输出的文件名来创建 XML 文件。
您可以将其用于自动化。它是一个小程序,用不依赖于 .NET 的语言编写,不需要安装。
【讨论】:
Win 10 PC 上的附加选项是找到“打开或关闭 Windows 功能”,然后会列出 .NET 框架。【参考方案6】:使用来自SignumFramework 的Signum.Utilities 库(您可以单独使用),您可以很好地获取它,而无需自己处理注册表:
AboutTools.FrameworkVersions().ToConsole();
//Writes in my machine:
//v2.0.50727 SP2
//v3.0 SP2
//v3.5 SP1
【讨论】:
查看此方法的代码,就它使用的注册表项而言,它不是很完整,并且会完全错过 .NET 1.0 并且不区分 .NET 2.0 (RTM) 和 .NET 2.0 SP1。它也没有考虑框架版本之间的依赖关系。 不是一个好的解决方案。当您可以用大约 3 行代码自己完成相同的工作时,没有充分的理由下载整个库只是为了获得 .NET 版本。作为程序员,您应该能够“自己处理注册表”。 @DannySmurf 我不同意。引入 .NET 3.0 时,MS 应该将其包装在 .NET API 中(只要我们在同一个 CLR 上拥有一层以上的 FX)。我宁愿让我的应用程序使用实用程序库,然后当 4.1、6.1、7.100 到达时,我可以只更新库和我的应用程序需要的 .NET 层的配置条目。当然,如果这些库都不起作用,这个论点就站不住脚。【参考方案7】:请参阅 How to: Determine Which .NET Framework Versions Are Installed (MSDN)。
MSDN 提出了一个似乎适用于版本 1-4 的函数示例。根据文章,方法输出为:
v2.0.50727 2.0.50727.4016 SP2
v3.0 3.0.30729.4037 SP2
v3.5 3.5.30729.01 SP1
v4
Client 4.0.30319
Full 4.0.30319
请注意,“4.5 及更高版本”还有另一个功能。
【讨论】:
【参考方案8】:.NET 4.5.1 更新
现在 .NET 4.5.1 可用,需要检查注册表中名为 Release 的键的实际值,而不仅仅是它的存在。值 378758 表示已安装 .NET Framework 4.5.1。但是,正如here 所述,此值在 Windows 8.1 上为 378675。
【讨论】:
【参考方案9】:我需要找出我的计算机上的 .NET 框架版本,我所做的只是转到控制面板并选择“卸载程序”选项。之后,我按名称对程序进行了排序,找到了 Microsoft .NET Framework 4 Client Profile。
【讨论】:
谢谢——我尝试过的所有其他“解决方案”都有缺陷并且无法正常工作。确实如此。 我来寻找此信息的原因是卸载程序下的内容完全不可靠,至少在涉及 .NET Framework 时是如此。【参考方案10】:对于 64 位操作系统,路径为:
HKEY_LOCAL_MACHINE\SOFTWARE\wow6432Node\Microsoft\NET Framework Setup\NDP\
【讨论】:
这只是“有点”真实。 64 位版本的 Windows 中的注册表分为 32 位和 64 位键(许多 32 位键与 64 位键同名)。Wow6432Node
注册表项是 WOW64 注册表反射器的一部分,它反映了 64 位和 32 位注册表视图之间的某些键和值。由于注册表会自动处理重定向和镜像,因此无需直接访问此键。【参考方案11】:
以下知识库文章中对此问题有 Microsoft 官方回答:
Article ID: 318785 - Last Review: November 7, 2008 - Revision: 20.1 How to determine which versions of the .NET Framework are installed and whether service packs have been applied
不幸的是,它似乎不起作用,因为 2.0 目录中的 mscorlib.dll 版本有 2.0 版本,而 3.0 或 3.5 目录中没有 mscorlib.dll 版本,即使安装了 3.5 SP1 。 ..为什么微软官方的回答会如此错误?
【讨论】:
+1 - 自从您最初链接到该页面后,微软似乎已经更新了该页面。所以看起来这可能是关于此事的最佳官方消息来源之一。 只能升到4.0【参考方案12】:枚举HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP
的子键。每个子项都是一个.NET 版本。如果它存在于机器上,它应该有 Install=1
值,一个显示服务包的 SP 值和一个 MSI=1
值,如果它是使用 MSI 安装的。 (例如,Windows Vista 上的 .NET 2.0 没有最后一个,因为它是操作系统的一部分。)
【讨论】:
我没有在我的机器 (XP Pro) 上找到这个密钥,但我确实有这个:HKLM\SOFTWARE\Microsoft\.NETFramework。但是,您描述的各种价值观对我来说并不存在。 如果您安装了 .NET 1.1 或更高版本,您应该拥有此密钥。您提到的密钥仅用于 .NET 1.0。 reg 查询“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP”【参考方案13】:Framework 4 beta 安装到不同的注册表项。
using System;
using System.Collections.ObjectModel;
using Microsoft.Win32;
class Program
static void Main(string[] args)
foreach(Version ver in InstalledDotNetVersions())
Console.WriteLine(ver);
Console.ReadKey();
public static Collection<Version> InstalledDotNetVersions()
Collection<Version> versions = new Collection<Version>();
RegistryKey NDPKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP");
if (NDPKey != null)
string[] subkeys = NDPKey.GetSubKeyNames();
foreach (string subkey in subkeys)
GetDotNetVersion(NDPKey.OpenSubKey(subkey), subkey, versions);
GetDotNetVersion(NDPKey.OpenSubKey(subkey).OpenSubKey("Client"), subkey, versions);
GetDotNetVersion(NDPKey.OpenSubKey(subkey).OpenSubKey("Full"), subkey, versions);
return versions;
private static void GetDotNetVersion(RegistryKey parentKey, string subVersionName, Collection<Version> versions)
if (parentKey != null)
string installed = Convert.ToString(parentKey.GetValue("Install"));
if (installed == "1")
string version = Convert.ToString(parentKey.GetValue("Version"));
if (string.IsNullOrEmpty(version))
if (subVersionName.StartsWith("v"))
version = subVersionName.Substring(1);
else
version = subVersionName;
Version ver = new Version(version);
if (!versions.Contains(ver))
versions.Add(ver);
【讨论】:
将Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP", true)
更改为 Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP")
以避免非管理员用户出现安全异常。
酷,我使用了 LinqPad,它给了我完美的结果! share.linqpad.net/5cjihh.linq
奇怪的是,您分享了一些小细节(例如安装了哪个服务包版本),但您的代码忽略了更重要的信息(如果仅部分或完全安装了框架)!将注册表项“Client”和“Full”视为相同是错误的。如果仅“客户端”键退出,例如 System.Web 将不可用。您的代码也应返回此重要信息!如果用户在控制面板中卸载了“.NET Framework 4 Extended”,将会丢失几个程序集。以上是关于确定安装了哪些 NET Framework 版本的主要内容,如果未能解决你的问题,请参考以下文章