using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using Microsoft.Win32;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Aneef.Apps
{
#region class FrameworkVersionDetection
///
/// Provides support for determining if a specific version of the .NET
/// Framework runtime is installed and the service pack level for the
/// runtime version.
///
public static class FrameworkUtils
{
#region events
#endregion
#region class-wide fields
// Constants representing registry key names and value names
private const string Netfx10RegKeyName = "Software\\Microsoft\\.NETFramework\\Policy\\v1.0";
private const string Netfx10RegKeyValue = "3705";
private const string Netfx10SPxMSIRegKeyName = "Software\\Microsoft\\Active Setup\\Installed Components\\{78705f0d-e8db-4b2d-8193-982bdda15ecd}";
private const string Netfx10SPxOCMRegKeyName = "Software\\Microsoft\\Active Setup\\Installed Components\\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}";
private const string Netfx11RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322";
private const string Netfx20RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727";
private const string Netfx30RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v3.0\\Setup";
private const string Netfx30SpRegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v3.0";
private const string Netfx30RegValueName = "InstallSuccess";
private const string Netfx35RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v3.5";
private const string NetfxStandardRegValueName = "Install";
private const string NetfxStandrdSpxRegValueName = "SP";
private const string NetfxStandardVersionRegValueName = "Version";
private const string Netfx20PlusBuildRegValueName = "Increment";
private const string Netfx35PlusBuildRegValueName = "Build";
private const string Netfx30PlusWCFRegKeyName = Netfx30RegKeyName + "\\Windows Communication Foundation";
private const string Netfx30PlusWPFRegKeyName = Netfx30RegKeyName + "\\Windows Presentation Foundation";
private const string Netfx30PlusWFRegKeyName = Netfx30RegKeyName + "\\Windows Workflow Foundation";
private const string Netfx30PlusWFPlusVersionRegValueName = "FileVersion";
private const string CardSpaceServicesRegKeyName = "System\\CurrentControlSet\\Services\\idsvc";
private const string CardSpaceServicesPlusImagePathRegName = "ImagePath";
private const string NetfxInstallRootRegKeyName = "Software\\Microsoft\\.NETFramework";
private const string NetFxInstallRootRegValueName = "InstallRoot";
private static readonly Version Netfx10Version = new Version(1, 0, 3705, 0);
private static readonly Version Netfx11Version = new Version(1, 1, 4322, 573);
private static readonly Version Netfx20Version = new Version(2, 0, 50727, 42);
private static readonly Version Netfx30Version = new Version(3, 0, 4506, 26);
private static readonly Version Netfx35Version = new Version(3, 5, 21022, 8);
private const string Netfx10VersionString = "v1.0.3705";
private const string Netfx11VersionString = "v1.1.4322";
private const string Netfx20VersionString = "v2.0.50727";
private const string NetfxMscorwks = "mscorwks.dll";
#endregion
#region private and internal properties and methods
#region properties
#endregion
#region methods
#region CheckFxVersion
///
/// Retrieves the .NET Framework version number from the registry
/// and validates that it is not a pre-release version number.
///
///
/// if the build number is greater than the
/// requested version; otherwise .
///
/// If mscorwks.dll can be found the version number of the DLL (looking
/// at the ProductVersion field) is also used.
///
private static bool CheckFxVersion(FrameworkVersion frameworkVersion)
{
bool valid = false;
string installPath = GetMscorwksPath(frameworkVersion);
FileVersionInfo fvi = null;
Version fxVersion;
if (!String.IsNullOrEmpty(installPath))
{
fvi = FileVersionInfo.GetVersionInfo(installPath);
}
switch (frameworkVersion)
{
case FrameworkVersion.Fx10:
fxVersion = GetNetfx10ExactVersion();
valid = (fvi != null) ? ((fxVersion >= Netfx10Version) && (new Version(fvi.ProductVersion) >= Netfx10Version)) : (fxVersion >= Netfx10Version);
break;
case FrameworkVersion.Fx11:
fxVersion = GetNetfx11ExactVersion();
valid = (fvi != null) ? ((fxVersion >= Netfx11Version) && (new Version(fvi.ProductVersion) >= Netfx11Version)) : (fxVersion >= Netfx11Version);
break;
case FrameworkVersion.Fx20:
fxVersion = GetNetfx20ExactVersion();
valid = (fvi != null) ? ((fxVersion >= Netfx20Version) && (new Version(fvi.ProductVersion) >= Netfx20Version)) : (fxVersion >= Netfx20Version);
break;
case FrameworkVersion.Fx30:
fxVersion = GetNetfxExactVersion(Netfx30RegKeyName, NetfxStandardVersionRegValueName);
valid = (fvi != null) ? ((fxVersion >= Netfx30Version) && (new Version(fvi.ProductVersion) >= Netfx20Version)) : (fxVersion >= Netfx30Version);
break;
case FrameworkVersion.Fx35:
fxVersion = GetNetfxExactVersion(Netfx35RegKeyName, NetfxStandardVersionRegValueName);
valid = (fvi != null) ? ((fxVersion >= Netfx35Version) && (new Version(fvi.ProductVersion) >= Netfx20Version)) : (fxVersion >= Netfx35Version);
break;
default:
valid = false;
break;
}
return valid;
}
#endregion
#region GetInstallRoot
///
/// Gets the installation root path for the .NET Framework.
///
/// A representing the installation root
/// path for the .NET Framework.
private static string GetInstallRoot()
{
string installRoot = String.Empty;
if (!GetRegistryValue(RegistryHive.LocalMachine, NetfxInstallRootRegKeyName, NetFxInstallRootRegValueName, RegistryValueKind.String, out installRoot))
{
throw new DirectoryNotFoundException("Cannot Find Installation Root");
}
return installRoot;
}
#endregion
#region GetMscorwksPath
///
/// Gets the path to the Mscorwks.DLL file.
///
///
/// The fully qualified path to the Mscorwks.DLL for the specified .NET
/// Framework.
///
private static string GetMscorwksPath(FrameworkVersion frameworkVersion)
{
string ret = String.Empty;
switch (frameworkVersion)
{
case FrameworkVersion.Fx10:
ret = Path.Combine(Path.Combine(GetInstallRoot(), Netfx10VersionString), NetfxMscorwks);
break;
case FrameworkVersion.Fx11:
ret = Path.Combine(Path.Combine(GetInstallRoot(), Netfx11VersionString), NetfxMscorwks);
break;
case FrameworkVersion.Fx20:
case FrameworkVersion.Fx30:
case FrameworkVersion.Fx35:
ret = Path.Combine(Path.Combine(GetInstallRoot(), Netfx20VersionString), NetfxMscorwks);
break;
default:
break;
}
return ret;
}
#endregion
#region GetNetfxSPLevel functions
#region GetNetfx10SPLevel
///
/// Detects the service pack level for the .NET Framework 1.0.
///
/// An representing the service pack
/// level for the .NET Framework.
/// Uses the detection method recommended at
/// http://blogs.msdn.com/astebner/archive/2004/09/14/229802.aspx
/// to determine what service pack for the .NET Framework 1.0 is
/// installed on the machine.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Int32.TryParse(System.String,System.Int32@)")]
private static int GetNetfx10SPLevel()
{
bool foundKey = false;
int servicePackLevel = -1;
string regValue;
foundKey = GetRegistryValue(RegistryHive.LocalMachine, Netfx10SPxMSIRegKeyName, NetfxStandardVersionRegValueName, RegistryValueKind.String, out regValue);
if (foundKey)
{
// This registry value should be of the format
// #,#,#####,# where the last # is the SP level
// Try to parse off the last # here
int index = regValue.LastIndexOf(',');
if (index > 0)
{
Int32.TryParse(regValue.Substring(index + 1), out servicePackLevel);
}
}
return servicePackLevel;
}
#endregion
#region GetNetfxSPLevel
///
/// Detects the service pack level for a version of .NET Framework.
///
/// The registry key name.
/// The registry value name.
/// An representing the service pack
/// level for the .NET Framework.
private static int GetNetfxSPLevel(string key, string value)
{
int regValue = 0;
// We can only get -1 if the .NET Framework is not
// installed or there was some kind of error retrieving
// the data from the registry
int servicePackLevel = -1;
if (GetRegistryValue(RegistryHive.LocalMachine, key, value, RegistryValueKind.DWord, out regValue))
{
servicePackLevel = regValue;
}
return servicePackLevel;
}
#endregion
#endregion
#region GetNetfxExactVersion functions
#region GetNetfx10ExactVersion
private static Version GetNetfx10ExactVersion()
{
bool foundKey = false;
Version fxVersion = new Version();
string regValue;
foundKey = GetRegistryValue(RegistryHive.LocalMachine, Netfx10SPxMSIRegKeyName, NetfxStandardVersionRegValueName, RegistryValueKind.String, out regValue);
if (foundKey)
{
// This registry value should be of the format
// #,#,#####,# where the last # is the SP level
// Try to parse off the last # here
int index = regValue.LastIndexOf(',');
if (index > 0)
{
string[] tokens = regValue.Substring(0, index).Split(',');
if (tokens.Length == 3)
{
fxVersion = new Version(Convert.ToInt32(tokens[0], NumberFormatInfo.InvariantInfo), Convert.ToInt32(tokens[1], NumberFormatInfo.InvariantInfo), Convert.ToInt32(tokens[2], NumberFormatInfo.InvariantInfo));
}
}
}
return fxVersion;
}
#endregion
#region GetNetfx11ExactVersion
private static Version GetNetfx11ExactVersion()
{
int regValue = 0;
// We can only get -1 if the .NET Framework is not
// installed or there was some kind of error retrieving
// the data from the registry
Version fxVersion = new Version();
if (GetRegistryValue(RegistryHive.LocalMachine, Netfx11RegKeyName, NetfxStandardRegValueName, RegistryValueKind.DWord, out regValue))
{
if (regValue == 1)
{
// In the strict sense, we are cheating here, but the registry key name itself
// contains the version number.
string[] tokens = Netfx11RegKeyName.Split(new string[] { "NDP\\v" }, StringSplitOptions.None);
if (tokens.Length == 2)
{
fxVersion = new Version(tokens[1]);
}
}
}
return fxVersion;
}
#endregion
#region GetNetfx20ExactVersion
private static Version GetNetfx20ExactVersion()
{
string regValue = String.Empty;
// We can only get -1 if the .NET Framework is not
// installed or there was some kind of error retrieving
// the data from the registry
Version fxVersion = new Version();
// If we have a Version registry value, use that.
try
{
fxVersion = GetNetfxExactVersion(Netfx20RegKeyName, NetfxStandardVersionRegValueName);
}
catch (IOException)
{
// If we hit an exception here, the Version registry key probably doesn't exist so try
// to get the version based on the registry key name itself.
if (GetRegistryValue(RegistryHive.LocalMachine, Netfx20RegKeyName, Netfx20PlusBuildRegValueName, RegistryValueKind.String, out regValue))
{
if (!String.IsNullOrEmpty(regValue))
{
string[] versionTokens = Netfx20RegKeyName.Split(new string[] { "NDP\\v" }, StringSplitOptions.None);
if (versionTokens.Length == 2)
{
string[] tokens = versionTokens[1].Split('.');
if (tokens.Length == 3)
{
fxVersion = new Version(Convert.ToInt32(tokens[0], NumberFormatInfo.InvariantInfo), Convert.ToInt32(tokens[1], NumberFormatInfo.InvariantInfo), Convert.ToInt32(tokens[2], NumberFormatInfo.InvariantInfo), Convert.ToInt32(regValue, NumberFormatInfo.InvariantInfo));
}
}
}
}
}
return fxVersion;
}
#endregion
#region GetNetfxExactVersion
///
/// Retrieves the .NET Framework version number from the registry.
///
/// The registry key name.
/// The registry value name.
/// A that represents the .NET
/// Framework version.
private static Version GetNetfxExactVersion(string key, string value)
{
string regValue = String.Empty;
// We can only get the default version if the .NET Framework
// is not installed or there was some kind of error retrieving
// the data from the registry
Version fxVersion = new Version();
if (GetRegistryValue(RegistryHive.LocalMachine, key, value, RegistryValueKind.String, out regValue))
{
if (!String.IsNullOrEmpty(regValue))
{
fxVersion = new Version(regValue);
}
}
return fxVersion;
}
#endregion
#endregion
#region GetRegistryValue
private static bool GetRegistryValue(RegistryHive hive, string key, string value, RegistryValueKind kind, out T data)
{
bool success = false;
data = default(T);
try
{
using (RegistryKey baseKey = RegistryKey.OpenRemoteBaseKey(hive, String.Empty))
{
if (baseKey != null)
{
using (RegistryKey registryKey = baseKey.OpenSubKey(key, RegistryKeyPermissionCheck.ReadSubTree))
{
if (registryKey != null)
{
// If the key was opened, try to retrieve the value.
RegistryValueKind kindFound = registryKey.GetValueKind(value);
if (kindFound == kind)
{
object regValue = registryKey.GetValue(value, null);
if (regValue != null)
{
data = (T)Convert.ChangeType(regValue, typeof(T), CultureInfo.InvariantCulture);
success = true;
}
}
}
}
}
}
}
catch (Exception ex)
{
success = false;
}
return success;
}
#endregion
#region IsNetfxInstalled functions
#region IsNetfx10Installed
///
/// Detects if the .NET 1.0 Framework is installed.
///
/// if the .NET Framework 1.0 is
/// installed; otherwise
/// Uses the detection method recommended at
/// http://msdn.microsoft.com/library/ms994349.aspx to determine
/// whether the .NET Framework 1.0 is installed on the machine.
///
private static bool IsNetfx10Installed()
{
bool found = false;
string regValue = string.Empty;
found = GetRegistryValue(RegistryHive.LocalMachine, Netfx10RegKeyName, Netfx10RegKeyValue, RegistryValueKind.String, out regValue);
return (found && CheckFxVersion(FrameworkVersion.Fx10));
}
#endregion
#region IsNetfx11Installed
///
/// Detects if the .NET 1.1 Framework is installed.
///
/// if the .NET Framework 1.1 is
/// installed; otherwise
/// Uses the detection method recommended at
/// http://msdn.microsoft.com/library/ms994339.aspx to determine
/// whether the .NET Framework 1.1 is installed on the machine.
///
private static bool IsNetfx11Installed()
{
bool found = false;
int regValue = 0;
if (GetRegistryValue(RegistryHive.LocalMachine, Netfx11RegKeyName, NetfxStandardRegValueName, RegistryValueKind.DWord, out regValue))
{
if (regValue == 1)
{
found = true;
}
}
return (found && CheckFxVersion(FrameworkVersion.Fx11));
}
#endregion
#region IsNetfx20Installed
///
/// Detects if the .NET 2.0 Framework is installed.
///
/// if the .NET Framework 2.0 is
/// installed; otherwise
/// Uses the detection method recommended at
/// http://msdn.microsoft.com/library/aa480243.aspx to determine
/// whether the .NET Framework 2.0 is installed on the machine.
///
private static bool IsNetfx20Installed()
{
bool found = false;
int regValue = 0;
if (GetRegistryValue(RegistryHive.LocalMachine, Netfx20RegKeyName, NetfxStandardRegValueName, RegistryValueKind.DWord, out regValue))
{
if (regValue == 1)
{
found = true;
}
}
return (found && CheckFxVersion(FrameworkVersion.Fx20));
}
#endregion
#region IsNetfx30Installed
///
/// Detects if the .NET 3.0 Framework is installed.
///
/// if the .NET Framework 3.0 is
/// installed; otherwise
/// Uses the detection method recommended at
/// http://msdn.microsoft.com/library/aa964979.aspx to determine
/// whether the .NET Framework 3.0 is installed on the machine.
///
private static bool IsNetfx30Installed()
{
bool found = false;
int regValue = 0;
// The .NET Framework 3.0 is an add-in that installs on top of
// the .NET Framework 2.0, so validate that both 2.0 and 3.0
// are installed.
if (IsNetfx20Installed())
{
// Check that the InstallSuccess registry value exists and equals 1.
if (GetRegistryValue(RegistryHive.LocalMachine, Netfx30RegKeyName, Netfx30RegValueName, RegistryValueKind.DWord, out regValue))
{
if (regValue == 1)
{
found = true;
}
}
}
// A system with a pre-release version of the .NET Fx 3.0 can have
// the InstallSuccess value. As an added verification, check the
// version number listed in the registry.
return (found && CheckFxVersion(FrameworkVersion.Fx30));
}
#endregion
#region IsNetfx35Installed
///
/// Detects if the .NET 3.5 Framework is installed.
///
/// if the .NET Framework 3.5 is
/// installed; otherwise
/// Uses the detection method recommended at
/// http://msdn.microsoft.com/library/cc160716.aspx to determine
/// whether the .NET Framework 3.5 is installed on the machine.
/// Also uses the method described at
/// http://blogs.msdn.com/astebner/archive/2008/07/13/8729636.aspx.
///
private static bool IsNetfx35Installed()
{
bool found = false;
int regValue = 0;
// The .NET Framework 3.0 is an add-in that installs on top of
// the .NET Framework 2.0 and 3.0, so validate that 2.0, 3.0,
// and 3.5 are installed.
if (IsNetfx20Installed() && IsNetfx30Installed())
{
// Check that the Install registry value exists and equals 1.
if (GetRegistryValue(RegistryHive.LocalMachine, Netfx35RegKeyName, NetfxStandardRegValueName, RegistryValueKind.DWord, out regValue))
{
if (regValue == 1)
{
found = true;
}
}
}
// A system with a pre-release version of the .NET Fx 3.5 can have
// the InstallSuccess value. As an added verification, check the
// version number listed in the registry.
return (found && CheckFxVersion(FrameworkVersion.Fx35));
}
#endregion
#endregion
#endregion
#endregion
#region public properties and methods
#region properties
#region InstalledFrameworkVersions
///
/// Gets an list of the installed .NET Framework
/// versions.
///
public static IEnumerable InstalledFrameworkVersions
{
get
{
if (IsInstalled(FrameworkVersion.Fx10))
{
yield return GetExactVersion(FrameworkVersion.Fx10);
}
if (IsInstalled(FrameworkVersion.Fx11))
{
yield return GetExactVersion(FrameworkVersion.Fx11);
}
if (IsInstalled(FrameworkVersion.Fx20))
{
yield return GetExactVersion(FrameworkVersion.Fx20);
}
if (IsInstalled(FrameworkVersion.Fx30))
{
yield return GetExactVersion(FrameworkVersion.Fx30);
}
if (IsInstalled(FrameworkVersion.Fx35))
{
yield return GetExactVersion(FrameworkVersion.Fx35);
}
}
}
#endregion
#endregion
#region methods
#region IsInstalled
#region IsInstalled(FrameworkVersion frameworkVersion)
///
/// Determines if the specified .NET Framework or Foundation Library is
/// installed on the local computer.
///
///
/// Determines if the specified .NET Framework version is installed
/// on the local computer.
///
/// The version of the .NET Framework to test.
///
/// if the specified .NET Framework
/// version is installed; otherwise .
public static bool IsInstalled(FrameworkVersion frameworkVersion)
{
bool ret = false;
switch (frameworkVersion)
{
case FrameworkVersion.Fx10:
ret = IsNetfx10Installed();
break;
case FrameworkVersion.Fx11:
ret = IsNetfx11Installed();
break;
case FrameworkVersion.Fx20:
ret = IsNetfx20Installed();
break;
case FrameworkVersion.Fx30:
ret = IsNetfx30Installed();
break;
case FrameworkVersion.Fx35:
ret = IsNetfx35Installed();
break;
default:
break;
}
return ret;
}
#endregion
#endregion
#region GetServicePackLevel
#region GetServicePackLevel(FrameworkVersion frameworkVersion)
///
/// Retrieves the service pack level for the specified .NET Framework or
/// Foundation Library.
///
///
/// Retrieves the service pack level for the specified .NET Framework
/// version.
///
/// The .NET Framework whose service pack
/// level should be retrieved.
/// An integer value representing
/// the service pack level for the specified .NET Framework version. If
/// the specified .NET Frameowrk version is not found, -1 is returned.
///
public static int GetServicePackLevel(FrameworkVersion frameworkVersion)
{
int servicePackLevel = -1;
switch (frameworkVersion)
{
case FrameworkVersion.Fx10:
servicePackLevel = GetNetfx10SPLevel();
break;
case FrameworkVersion.Fx11:
servicePackLevel = GetNetfxSPLevel(Netfx11RegKeyName, NetfxStandrdSpxRegValueName);
break;
case FrameworkVersion.Fx20:
servicePackLevel = GetNetfxSPLevel(Netfx20RegKeyName, NetfxStandrdSpxRegValueName);
break;
case FrameworkVersion.Fx30:
servicePackLevel = GetNetfxSPLevel(Netfx30SpRegKeyName, NetfxStandrdSpxRegValueName);
break;
case FrameworkVersion.Fx35:
servicePackLevel = GetNetfxSPLevel(Netfx35RegKeyName, NetfxStandrdSpxRegValueName);
break;
default:
break;
}
return servicePackLevel;
}
#endregion
#endregion
#region GetExactVersion
#region GetExactVersion(FrameworkVersion frameworkVersion)
///
/// Retrieves the exact version number for the specified .NET Framework or
/// Foundation Library.
///
///
/// Retrieves the exact version number for the specified .NET Framework
/// version.
///
/// The .NET Framework whose version should be
/// retrieved.
/// A version representing
/// the exact version number for the specified .NET Framework version.
/// If the specified .NET Frameowrk version is not found, a
/// is returned that represents a 0.0.0.0 version
/// number.
///
public static Version GetExactVersion(FrameworkVersion frameworkVersion)
{
Version fxVersion = new Version();
switch (frameworkVersion)
{
case FrameworkVersion.Fx10:
fxVersion = GetNetfx10ExactVersion();
break;
case FrameworkVersion.Fx11:
fxVersion = GetNetfx11ExactVersion();
break;
case FrameworkVersion.Fx20:
fxVersion = GetNetfx20ExactVersion();
break;
case FrameworkVersion.Fx30:
fxVersion = GetNetfxExactVersion(Netfx30RegKeyName, NetfxStandardVersionRegValueName);
break;
case FrameworkVersion.Fx35:
fxVersion = GetNetfxExactVersion(Netfx35RegKeyName, NetfxStandardVersionRegValueName);
break;
default:
break;
}
return fxVersion;
}
#endregion
#endregion
#endregion
#endregion
}
#endregion
#region enum FrameworkVersion
///
/// Specifies the .NET Framework versions
///
public enum FrameworkVersion
{
///
/// .NET Framework 1.0
///
Fx10,
///
/// .NET Framework 1.1
///
Fx11,
///
/// .NET Framework 2.0
///
Fx20,
///
/// .NET Framework 3.0
///
Fx30,
///
/// .NET Framework 3.5
///
Fx35,
}
#endregion
}