如何可靠地检测到实际的.NET 4.5版本安装?

我的实际问题是,我遇到了两个版本的.NET 4.5完整设置:

  • 一个(可能)较旧的,这在下载SQL Server数据工具时也是可用的
    • 大小: 50,349,920
    • md5: a5e81d1b3905ada0a6e35fd6c6a2e1f4
  • 一个(可能)更新今天早上从这里下载: http : //www.microsoft.com/visualstudio/eng/downloads
    • 大小: 50,352,408
    • md5: d02dc8b69a702a47c083278938c4d2f1

这两个设置的版本是4.5.50709.17929 。 在里面,主要区别是netfx_Full.mzz文件,但是在用7-zip解压缩内容后,即使文件内容不同,我也会得到很多相同版本的文件(我已经检查了大约20个随机文件约426),所以我真的不知道哪一个更新。

有没有一种方法来可靠地检测到已安装的.NET 4.5运行时的实际版本,所以只有在真正需要时才能运行安装程序?

更新

我已经检查了所有具有不同内容的426个文件,并且所有这些文件在两个设置中都具有相同的ProductVersion和FileVersion。 所以,registry或文件校验和是下一步。

更新2

在registry中列出的版本对于这两个设置是相同的: 4.5.50709

更新3

.NET 4.5.2现在可用:

此版本的.NET Framework与.NET Framework 3.5 SP1及更早版本并行运行,但是为.NET Framework 4,.NET Framework 4.5和.NET Framework 4.5.1执行就地更新。

MS最近在某些情况下修补了.NET 4.5以恢复与.NET 4.0的向后兼容性(请参阅http://blogs.msdn.com/b/dotnet/archive/2012/10/17/net-framework-4-5-off -to-a-great-start.aspx )。

MS可能会更新这些更改(以便升级到.NET 4.5的用户不会遇到问题),但我不知道为什么他们不会更改安装程序的版本号。

另外请注意,.NET版本号和System.Environment.Version报告的运行时版本号有所不同。 后者仍然是4.0.30319。*对于.NET 4.5,只有版本号更改(使用.NET 4.5更新以及每个安全更新)。

下面是在野外观察到的运行时版本的一些例子:

基地4.0

  • 4.0.30319.1 = .NET 4.0 RTM
  • 4.0.30319.269 = Windows XP SP3,7,7 SP1上的.NET 4.0(带有MS12-035 GDR安全更新)
  • 4.0.30319.276 = Windows XP SP3上的.NET 4.0(4.0.3运行时更新)
  • 4.0.30319.296 = Windows XP SP3,7上的.NET 4.0(带有MS12-074 GDR安全更新)
  • 4.0.30319.544 = Windows XP SP3,7,7 SP1上的.NET 4.0(带有MS12-035 LDR安全更新)
  • 4.0.30319.1008 = Windows XP SP3,7,7 SP1上的.NET 4.0(带有MS13-052 GDR安全更新)
  • 4.0.30319.1022 = Windows XP SP3,7,7 SP1上的.NET 4.0( MS14-009 GDR安全更新)
  • 4.0.30319.1026 = Windows XP SP3,7,7 SP1上的.NET 4.0(带有MS14-057 GDR安全更新)
  • 4.0.30319.2034 = Windows XP SP3,7,7 SP1上的.NET 4.0(带有MS14-009 LDR安全更新)

4.5

  • 4.0.30319.17626 = .NET 4.5 RC
  • 4.0.30319.17929 = .NET 4.5 RTM
  • 4.0.30319.18010 = Windows 8上的.NET 4.5
  • 4.0.30319.18052 = Windows 7 SP1 64位上的.NET 4.5
  • 4.0.30319.18063 = Windows 7 SP1 64位上的.NET 4.5(带有MS14-009安全更新)

4.5.1

  • 4.0.30319.18408 = Windows 7 SP1 64位上的.NET 4.5.1
  • 4.0.30319.18444 = Windows 7 SP1 64位上的.NET 4.5.1(带有MS14-009安全更新)
  • 4.0.30319.34014 = Windows 8.1 64位上的.NET 4.5.1

4.5.2

  • 4.0.30319.34209 = Windows 7 SP1 64位上的.NET 4.5.2
  • 4.0.30319.34209 = Windows 8.1 64位上的.NET 4.5.2

4.6及更高版本

  • 4.0.30319.42000

我的Windows Update历史logging中没有看到任何.NET更新,所以我猜想v18010的更新已经作为KB 2756872的一部分安装。

更新:显然,微软更新了.NET 4.5安装程序,因为原始下载中的数字签名有错误。 KB 2770445 。

 public class DA { public static class VersionNetFramework { public static string Get45or451FromRegistry() {//https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) { int releaseKey = Convert.ToInt32(ndpKey.GetValue("Release")); if (true) { return (@"Version: " + CheckFor45DotVersion(releaseKey)); } } } // Checking the version using >= will enable forward compatibility, // however you should always compile your code on newer versions of // the framework to ensure your app works the same. private static string CheckFor45DotVersion(int releaseKey) {//https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx if (releaseKey >= 394271) return "4.6.1 installed on all other Windows OS versions or later"; if (releaseKey >= 394254) return "4.6.1 installed on Windows 10 or later"; if (releaseKey >= 393297) return "4.6 installed on all other Windows OS versions or later"; if (releaseKey >= 393295) return "4.6 installed with Windows 10 or later"; if (releaseKey >= 379893) return "4.5.2 or later"; if (releaseKey >= 378758) return "4.5.1 installed on Windows 8, Windows 7 SP1, or Windows Vista SP2 or later"; if (releaseKey >= 378675) return "4.5.1 installed with Windows 8.1 or later"; if (releaseKey >= 378389) return "4.5 or later"; return "No 4.5 or later version detected"; } public static string GetVersionFromRegistry() {//https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx string res = @""; // Opens the registry key for the .NET Framework entry. using (RegistryKey ndpKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ""). OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\")) { // As an alternative, if you know the computers you will query are running .NET Framework 4.5 // or later, you can use: // using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, // RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\")) foreach (string versionKeyName in ndpKey.GetSubKeyNames()) { if (versionKeyName.StartsWith("v")) { RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName); string name = (string)versionKey.GetValue("Version", ""); string sp = versionKey.GetValue("SP", "").ToString(); string install = versionKey.GetValue("Install", "").ToString(); if (install == "") //no install info, must be later. res += (versionKeyName + " " + name) + Environment.NewLine; else { if (sp != "" && install == "1") { res += (versionKeyName + " " + name + " SP" + sp) + Environment.NewLine; } } if (name != "") { continue; } foreach (string subKeyName in versionKey.GetSubKeyNames()) { RegistryKey subKey = versionKey.OpenSubKey(subKeyName); name = (string)subKey.GetValue("Version", ""); if (name != "") sp = subKey.GetValue("SP", "").ToString(); install = subKey.GetValue("Install", "").ToString(); if (install == "") //no install info, must be later. res += (versionKeyName + " " + name) + Environment.NewLine; else { if (sp != "" && install == "1") { res += (" " + subKeyName + " " + name + " SP" + sp) + Environment.NewLine; } else if (install == "1") { res += (" " + subKeyName + " " + name) + Environment.NewLine; } } } } } } return res; } public static string GetUpdateHistory() {//https://msdn.microsoft.com/en-us/library/hh925567(v=vs.110).aspx string res=@""; using (RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Updates")) { foreach (string baseKeyName in baseKey.GetSubKeyNames()) { if (baseKeyName.Contains(".NET Framework") || baseKeyName.StartsWith("KB") || baseKeyName.Contains(".NETFramework")) { using (RegistryKey updateKey = baseKey.OpenSubKey(baseKeyName)) { string name = (string)updateKey.GetValue("PackageName", ""); res += baseKeyName + " " + name + Environment.NewLine; foreach (string kbKeyName in updateKey.GetSubKeyNames()) { using (RegistryKey kbKey = updateKey.OpenSubKey(kbKeyName)) { name = (string)kbKey.GetValue("PackageName", ""); res += (" " + kbKeyName + " " + name) + Environment.NewLine; if (kbKey.SubKeyCount > 0) { foreach (string sbKeyName in kbKey.GetSubKeyNames()) { using (RegistryKey sbSubKey = kbKey.OpenSubKey(sbKeyName)) { name = (string)sbSubKey.GetValue("PackageName", ""); if (name == "") name = (string)sbSubKey.GetValue("Description", ""); res += (" " + sbKeyName + " " + name) + Environment.NewLine; } } } } } } } } } return res; } } } 

你可以随时去Windows / Microsoft.net /框架/ 4.0.30319,看看system.dll文件…右键单击属性,看看去详细..应该告诉你的版本… system.dll for 4.5.2