How to reliably detect the actual .NET 4.5 version installed?
My actual problem is that I have encountered two versions of .NET 4.5 full setups:
- a (possibly) older one, which is also available when downloading SQL Server Data Tools
- size:
50,349,920
- md5:
a5e81d1b3905ada0a6e35fd6c6a2e1f4
- size:
- a (possibly) newer one downloaded this morning from here: http://www.microsoft.com/visualstudio/eng/downloads
- size:
50,352,408
- md5:
d02dc8b69a702a47c083278938c4d2f1
- size:
The version for both setups is 4.5.50709.17929
. Inside, the main difference is the netfx_Full.mzz
file, but after extracting the content with 7-zip I end up with a lot of files with the same version, even if the file content is different (I have checked about 20 random files from about 426), so I can't really tell which one is newer.
Is there a way to reliably detect the actual version of the installed .NET 4.5 runtime, so I can run the setup only if it's really required?
Update
I have checked all the 426 files that have different content, and all of them are having the same ProductVersion and FileVersion in both setups. So, registry or file checksums are the next step.
Update 2
The version listed in the registry is the same for both setups: 4.5.50709
Update 3
.NET 4.5.2 is now available:
This version of the .NET Framework runs side-by-side with the .NET Framework 3.5 SP1 and earlier versions, but performs an in-place update for the .NET Framework 4, .NET Framework 4.5 and .NET Framework 4.5.1.
Solution 1:
MS recently patched .NET 4.5 to restore backwards compatibility with .NET 4.0 in some scenarios (see http://blogs.msdn.com/b/dotnet/archive/2012/10/17/net-framework-4-5-off-to-a-great-start.aspx).
It's possible that MS updated the setup with these changes (so that users upgrading to .NET 4.5 don't run into compat trouble), though I don't know why they wouldn't change the version number on the setup.
Also, note that there's a difference between the .NET version number and the runtime version number as reported by System.Environment.Version
. The latter still is 4.0.30319.* for .NET 4.5, only the revision number changes (with the .NET 4.5 update, and also with every security update).
Here are some examples of runtime versions observed in the wild:
Base 4.0
- 4.0.30319.1 = .NET 4.0 RTM
- 4.0.30319.269 = .NET 4.0 on Windows XP SP3, 7, 7 SP1 (with MS12-035 GDR security update)
- 4.0.30319.276 = .NET 4.0 on Windows XP SP3 (4.0.3 Runtime update)
- 4.0.30319.296 = .NET 4.0 on Windows XP SP3, 7 (with MS12-074 GDR security update)
- 4.0.30319.544 = .NET 4.0 on Windows XP SP3, 7, 7 SP1 (with MS12-035 LDR security update)
- 4.0.30319.1008 = .NET 4.0 on Windows XP SP3, 7, 7 SP1 (with MS13-052 GDR security update)
- 4.0.30319.1022 = .NET 4.0 on Windows XP SP3, 7, 7 SP1 (with MS14-009 GDR security update)
- 4.0.30319.1026 = .NET 4.0 on Windows XP SP3, 7, 7 SP1 (with MS14-057 GDR security update)
- 4.0.30319.2034 = .NET 4.0 on Windows XP SP3, 7, 7 SP1 (with MS14-009 LDR security update)
4.5
- 4.0.30319.17626 = .NET 4.5 RC
- 4.0.30319.17929 = .NET 4.5 RTM
- 4.0.30319.18010 = .NET 4.5 on Windows 8
- 4.0.30319.18052 = .NET 4.5 on Windows 7 SP1 64-bit
- 4.0.30319.18063 = .NET 4.5 on Windows 7 SP1 64-bit (with MS14-009 security update)
4.5.1
- 4.0.30319.18408 = .NET 4.5.1 on Windows 7 SP1 64-bit
- 4.0.30319.18444 = .NET 4.5.1 on Windows 7 SP1 64-bit (with MS14-009 security update)
- 4.0.30319.34014 = .NET 4.5.1 on Windows 8.1 64-bit
4.5.2
- 4.0.30319.34209 = .NET 4.5.2 on Windows 7 SP1 64-bit
- 4.0.30319.34209 = .NET 4.5.2 on Windows 8.1 64-bit
4.6 and later
- 4.0.30319.42000
I don't see any .NET updates in my Windows Update history, so I guess the update to v18010 got installed as part of KB 2756872.
Update: apparently Microsoft updated the .NET 4.5 setup due a mistake with the digital signatures in the original download. KB 2770445.
Solution 2:
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;
}
}
}
Solution 3:
If someone needs the System.Environment.Version
value against the .net version, arranged in a table (need to perform =Vlookup
with excel etc...)
here is a plunker I have created for that.
enter the link above and you will be able to copy the this table image:
Solution 4:
you can always go to the Windows/Microsoft.net/Framework/4.0.30319 and look at the system.dll file...right click properties and see go to details..should show you the version... system.dll for 4.5.2