Click here to Skip to main content
15,892,298 members
Articles / Programming Languages / Visual Basic
Article

Using managed code to detect what .NET Framework versions and service packs are installed

Rate me:
Please Sign up or sign in to vote.
4.85/5 (39 votes)
8 Sep 2008CPOL9 min read 281.7K   3K   172   70
Explains how to use managed code to detect which .NET Framework versions and service packs are installed.

Introduction

Developers are increasingly faced with the possibility of multiple .NET Framework versions being installed on the same machine. The .NET architecture was designed to allow multiple versions of a component to be installed and run at the same time on a single system, and this side-by-side deployment extends to the .NET Framework itself. By allowing multiple versions of the .NET Framework to be installed on the same computer, applications built with version 1.0 of the .NET Framework can run using the newer versions, or continue running with the earlier version. By default, client-side applications will use the version of the .NET Framework with which they were built, even when a newer version is available on the client.

There are situations, however, where it becomes important, or at least interesting, to know which versions of the .NET Framework are installed. Typically, this is done during installation, and the best way to do this is using unmanaged C++. Remember, you can only run managed code if a version of the .NET Framework is already installed, so this class is not guaranteed to work as part of an installation process. Aaron Stebner has a great set of blog posts [^] (including sample code) that shows how to do this in C++, and you can also check out this article [^].

While C++ may be the best way to do this, there are still times when this same functionality is needed in managed code. After searching both Google and CodeProject, I was unable to find a satisfactory solution in managed code. As a result, I decided to port Aaron's code to C#. This code uses Generics, so it is only compatible with version 2.0 or later of the .NET Framework.

Background

The correct way to determine if a specific version of the .NET Framework is installed is to look in the Registry. Aaron and a few readers of this article have pointed out that this solution, while the recommended way, is not 100% accurate in all situations. There are occasions when the Registry keys are orphaned, such as OS reinstalls. The solution presented by Aaron uses a technique by Junfeng Zhang [^] which loads mscoree.dll and uses some of its API functions to query for the presence of specific versions of the .NET Framework. The problem with this approach is that it only works from unmanaged code.

I took a slightly different approach, which more closely follows how the .NET Framework 3.5 setup checks for its prerequisites [^]. This approach looks for the presence of mscorwks.dll and, if found, verifies that the version number of the file is greater than or equal to the requested .NET Framework version, in addition to verifying that the Registry value is greater than or equal to the requested .NET Framework version. Consequently, if the file isn't found, I simply test the Registry value.

Using the code

Each major release of the .NET Framework has changed the Registry location and, in some cases, the keys and value names to look for in the Registry. In order to consolidate checking all of the various Registry keys and help isolate changes for future versions of the .NET Framework, the FrameworkVersionDetection class was created. This class exposes the following public methods and properties:

  • public static bool IsInstalled(FrameworkVersion frameworkVersion)
  • public static bool IsInstalled(WindowsFoundationLibrary foundationLibrary)
  • public static int GetServicePackLevel(FrameworkVersion frameworkVersion)
  • public static int GetServicePackLevel(WindowsFoundationLibrary foundationLibrary)
  • public static Version GetExactVersion(FrameworkVersion frameworkVersion)
  • public static Version GetExactVersion(WindowsFoundationLibrary foundationLibrary)
  • public static IEnumerable InstalledFrameworkVersions

As you can see, all of these functions use either the FrameworkVersion or the WindowsFoundationLibrary enumeration. These enumerations have the following definition:

C#
/// <summary>/// Specifies the .NET Framework versions
///// </summary>
public enum FrameworkVersion
{
  /// <summary>
  /// .NET Framework 1.0
  /// </summary>
  Fx10,

  /// <summary>
  /// .NET Framework 1.1
  /// </summary>
  Fx11,

  /// <summary>
  /// .NET Framework 2.0
  /// </summary>
  Fx20,

  /// <summary>
  /// .NET Framework 3.0
  /// </summary>
  Fx30,

  /// <summary>
  /// .NET Framework 3.5
  /// </summary>
  Fx35,
}

/// <summary>
/// Specifies the .NET 3.0 Windows Foundation Library
/// </summary>
public enum WindowsFoundationLibrary
{
  /// <summary>
  /// Windows Communication Foundation
  /// </summary>
  WCF,

  /// <summary>
  /// Windows Presentation Foundation
  /// </summary>
  WPF,

  /// <summary>
  /// Windows Workflow Foundation
  /// </summary>
  WF,

  /// <summary>
  /// Windows CardSpace
  /// </summary>
  CardSpace,
}

A complete example in C# looks like this:

C#
bool fx10Installed = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx10);
bool fx11Installed = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx11);
bool fx20Installed = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx20);
bool fx30Installed = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx30);
bool fx35Installed = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx35);

Console.WriteLine(".NET Framework 1.0 installed? {0}", fx10Installed);
if (fx10Installed)
{
   Console.WriteLine(".NET Framework 1.0 Exact Version: {0}",
      FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx10));
   Console.WriteLine(".NET Framework 1.0 Service Pack: {0}",
      FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx10));
}
Console.WriteLine();

Console.WriteLine(".NET Framework 1.1 installed? {0}", fx11Installed);
if (fx11Installed)
{
   Console.WriteLine(".NET Framework 1.1 Exact Version: {0}",
     FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx11));
   Console.WriteLine(".NET Framework 1.1 Service Pack: {0}",
     FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx11));
}
Console.WriteLine();

Console.WriteLine(".NET Framework 2.0 installed? {0}", fx20Installed);
if (fx20Installed)
{
   Console.WriteLine(".NET Framework 2.0 Exact Version: {0}",
     FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx20));
   Console.WriteLine(".NET Framework 2.0 Service Pack: {0}",
     FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx20));
}
Console.WriteLine();

Console.WriteLine(".NET Framework 3.0 installed? {0}", fx30Installed);
if (fx30Installed)
{
   Console.WriteLine(".NET Framework 3.0 Exact Version: {0}",
     FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx30));
   Console.WriteLine(".NET Framework 3.0 Service Pack: {0}",
     FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx30));

   bool fx30PlusWCFInstalled = 
        FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.WCF);
   bool fx30PlusWPFInstalled = 
        FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.WPF);
   bool fx30PlusWFInstalled = 
        FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.WF);
   bool fx30PlusCardSpacesInstalled =
      FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.CardSpace);

   Console.WriteLine();

   Console.WriteLine("Windows Communication Foundation installed? {0}", 
                     fx30PlusWCFInstalled);
   if (fx30PlusWCFInstalled)
   {
     Console.WriteLine("Windows Communication Foundation Exact Version: {0}",
       FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.WCF));
   }
   Console.WriteLine();

   Console.WriteLine("Windows Presentation Foundation installed? {0}", 
                     fx30PlusWPFInstalled);
   if (fx30PlusWPFInstalled)
   {
     Console.WriteLine("Windows Presentation Foundation Exact Version: {0}",
       FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.WPF));
   }
   Console.WriteLine();

   Console.WriteLine("Windows Workflow Foundation installed? {0}", 
                     fx30PlusWFInstalled);
   if (fx30PlusWFInstalled)
   {
     Console.WriteLine("Windows Workflow Foundation Exact Version: {0}",
       FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.WF));
   }
   Console.WriteLine();

   Console.WriteLine("Windows CardSpaces installed? {0}", 
                     fx30PlusCardSpacesInstalled);
   if (fx30PlusCardSpacesInstalled)
   {
     Console.WriteLine("Windows CardSpaces Exact Version: {0}",
       FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.CardSpace));
   }
   Console.WriteLine();
}
Console.WriteLine();

Console.WriteLine(".NET Framework 3.5 installed? {0}", fx35Installed);
if (fx35Installed)
{
   Console.WriteLine(".NET Framework 3.5 Exact Version: {0}",
     FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx35));
   Console.WriteLine(".NET Framework 3.5 Service Pack: {0}",
     FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx35));
}
 
foreach (Version fxVersion in FrameworkVersionDetection.InstalledFrameworkVersions)
{
   Console.WriteLine(fxVersion .ToString());
}

Registry keys

The Registry keys used to determine if a particular version of the .NET Framework is installed are:

Framework VersionRegistry Key
1.0HKLM\Software\Microsoft\.NETFramework\Policy\v1.0\3705
1.1HKLM\Software\Microsoft\NET Framework Setup\NDP\v1.1.4322\Install
2.0HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\Install
3.0HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\InstallSuccess
3.5HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.5\Install

For the .NET Framework v1.0, this is a string value; all of the other versions use a DWORD value which, if present and set to 1, indicates that version of the Framework is installed. For .NET 3.0, it is important to also verify that .NET 2.0 is also installed, and for .NET 3.5, you should verify that both .NET 2.0 and 3.0 are also installed. In order to determine the Service Pack level, the following Registry keys are used:

Framework VersionRegistry Key

1.0

(Windows Media Center

or

Windows XP Tablet Edition)

HKLM\Software\Microsoft\Active Setup\Installed Components\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}\Version
1.0HKLM\Software\Microsoft\Active Setup\Installed Components\{78705f0d-e8db-4b2d-8193-982bdda15ecd}\Version
1.1HKLM\Software\Microsoft\NET Framework Setup\NDP\v1.1.4322\SP
2.0HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\SP
3.0HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\SP
3.5HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.5\SP

As you can see, in order to determine the Service Pack level for the .NET Framework v1.0, it is necessary to know if the Operating System is Windows Media Center or Windows XP Tablet Edition before looking in the Registry. To complicate things even more, for .NET 1.0, the Registry value at either of these keys is a string value of the format #,#,####,#. The last # is the Service Pack level. For all of the other versions, this is a DWORD value indicating the Service Pack level.

Finally, to determine the exact version number of the Framework, we look at the following Registry keys:

Framework VersionRegistry Key

1.0

(Windows Media Center

or

Windows XP Tablet Edition)

HKLM\Software\Microsoft\Active Setup\Installed Components\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}\Version
1.0HKLM\Software\Microsoft\Active Setup\Installed Components\{78705f0d-e8db-4b2d-8193-982bdda15ecd}\Version
1.1HKLM\Software\Microsoft\NET Framework Setup\NDP\v1.1.4322
2.0

HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\Version

- or -

HKLM\Software\Microsoft\NET Framework Setup\NDP\v2.0.50727\Increment

3.0HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Version
3.5HKLM\Software\Microsoft\NET Framework Setup\NDP\v3.5\Version

Again, for .NET 1.0, it is necessary to know if the Operating System is Windows Media Center or Windows XP Tablet Edition before looking in the Registry, and the Registry value at either of these keys is a string value of the format #,#,####,#. The #,#,#### portion of the string is the Framework version.

For .NET 1.1, we use the name of the Registry key itself, which represents the version number, and for .NET 2.0, there are two different methods for determining the exact version number. If .NET 2.0 Original Release (RTM) is installed, then the version number is derived from the key name itself and the Increment Registry value (which is a string value representing the fourth part of the version number). Service Pack 1 for the .NET Framework 2.0 added the Version Registry value.

.NET Framework v3.0 Foundation libraries

In order to detect if any of the Foundation libraries are installed, you need to use the InstallSuccess Registry value from following rRegistry keys:

Foundation LibraryRegistry Key
Windows Communication FoundationHKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\Windows Communication Foundation
Windows Presentation FoundationHKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\Windows Presentation Foundation
Windows Workflow FoundationHKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\Windows Workflow Foundation

As is the case for the .NET Framework 3.0 itself, this is a DWORD value which, if present and set to 1, indicates that the Foundation library is installed. There have not been any service packs released specifically for the Foundation libraries, so at this time, there are no Registry keys to evaluate.

Determining the exact version number for any of the Foundation libraries uses the following Registry keys:

Foundation LibraryRegistry Key
Windows Communication FoundationHKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\Windows Communication Foundation\Version
Windows Presentation FoundationHKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\Windows Presentation Foundation\Version
Windows Workflow FoundationHKLM\Software\Microsoft\NET Framework Setup\NDP\v3.0\Setup\Windows Workflow Foundation\FileVersion

Determining this information for Windows CardSpace is not as straightforward. The Registry can still be used to determine if Windows CardSpace is installed:

HKLM\System\CurrentControlSet\Services\idsvc\ImagePath

In order to determine the exact version, we must interrogate the file using the FileVersionInfo class and the value returned from the Registry key.

Points of interest

The public methods are simply wrappers that determine which private function should be called. These private functions, in turn, query the appropriate Registry keys and process the result. However, the real work is done in the GetRegistryValue<T> function. This is a generic function that returns a bool value indicating if the requested Registry key was found and an out parameter that contains the value. By making this a generic function, I was able to simply encapsulate all of the Registry access in a single function, and was able to more closely match the original C++ code provided by Aaron. The GetRegistryValue<T> function is defined as:

C#
private static bool GetRegistryValue<T>(RegistryHive hive, string key, string value,
        RegistryValueKind kind, out T data)
{
  bool success = false;
  data = default(T);

  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;
                 }
              }
           }
        }
     }
  }
  return success;
}

It is important to note that if the user does not have the appropriate permissions to access the Registry, this function will throw an exception that will bubble up to the original caller. This was intentionally done to allow the caller the ability to take different actions based on the exception thrown.

Future considerations

I have not tested this code on any of the .NET Compact Framework versions, or determined how to detect the installed Compact Framework versions. If someone wants to do this investigation and let me know their findings, I will update the code accordingly.

If someone wants to test this on Windows XP 64-bit and Windows Vista 64-bit systems, let me know if it runs properly, and if not, what the errors are, and I will correct them.

Revision history

  • 8-September-2008:
    • Revised portions of the article to simplify the way the Registry key information is displayed.
    • Added a new InstalledFrameworkVersions property which returns an IEnumerable of Version objects representing the collection of installed frameworks.
    • Added some additional safety checks to help eliminate false positives from orphaned Registry keys.
    • Changed to using SandCastle for the documentation.
  • 17-August-2007:
    • Updated the Registry key for detecting the exact version of the .NET Framework v3.5 Beta 2.
  • 06-March-2007:
    • Corrected a few typographical errors.
  • 10-February-2007:
    • Corrected the Registry key path for the .NET 3.0 core keys.
    • Added a note asking for people to test this code on 64-bit XP and Vista and let me know what errors occur so I can correct them.
  • 04-February-2007:
    • Added information for the .NET Framework 3.5 (Orcas) January CTP.
    • Added "best guess" support for checking Service Pack level for the .NET Framework v3.0.
    • Added the GetExactVersion function; renamed IsFrameworkInstalled to IsInstalled, and added an overload to handle the Foundation libraries (WPF, WCF, WF, and CardSpace).
    • Added an overload to GetServicePackLevel to handle the Foundation libraries.
    • Added the WindowsFoundationLibrary enum.
    • Added Registry keys to show how to retrieve the version number information for the Framework.
    • Updated the sample code in the article.
    • Updated the formatting of the article.
    • Changed the article title and explanation to help clarify that this isn't intended to be run as part of an installer.
  • 03-February-2007:
    • Original article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I am a Microsoft C# MVP, author, speaker, blogger, and software developer. I also created the WP Requests and WinStore Requests sites for Windows Phone and Windows Sotre apps as well as several open source projects.

I've been involved with computers in one way or another for as long as I can remember, but started professionally in 1993. Although my primary focus right now is commercial software applications, I prefer building infrastructure components, reusable shared libraries and helping companies define, develop and automate process and code standards and guidelines.

Comments and Discussions

 
SuggestionUpdate: Detect .NET 4.5 and .NET 4.5.1 Pin
adriancs20-Nov-13 13:55
mvaadriancs20-Nov-13 13:55 
GeneralMy vote of 5 Pin
Gun Gun Febrianza24-Feb-12 21:14
Gun Gun Febrianza24-Feb-12 21:14 
QuestionRe: Where is InstalledFrameworkVersions Pin
robvon20-Jan-12 16:08
robvon20-Jan-12 16:08 
GeneralNet Framewrok 4.0 Update Code [modified] Pin
JavierJJJ27-Apr-11 0:26
JavierJJJ27-Apr-11 0:26 
I post the update for the code:


File FrameworkVersion.cs
using System;

namespace Campari.Software
{
	#region enum FrameworkVersion
    
    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,

        /// .NET Framework 4.0 Client
        Fx40C,

        /// .NET Framework 4.0 Full
        Fx40F
    }
    #endregion
}



File FrameworkVersionDetection.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

using Microsoft.Win32;

using Campari.Software.InteropServices;
using System.IO;
using System.Diagnostics;

namespace Campari.Software
{
    #region class FrameworkVersionDetection
    /// <summary>
    /// Provides support for determining if a specific version of the .NET
    /// Framework runtime is installed and the service pack level for the
    /// runtime version.
    /// </summary>
    public static class FrameworkVersionDetection
    {

        #region class-wide fields

        const string Netfx10RegKeyName = "Software\\Microsoft\\.NETFramework\\Policy\\v1.0";
        const string Netfx10RegKeyValue = "3705";
        const string Netfx10SPxMSIRegKeyName = "Software\\Microsoft\\Active Setup\\Installed Components\\{78705f0d-e8db-4b2d-8193-982bdda15ecd}";
        const string Netfx10SPxOCMRegKeyName = "Software\\Microsoft\\Active Setup\\Installed Components\\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}";
        const string Netfx10SPxRegValueName = "Version";
        const string Netfx11RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322";
        const string Netfx20RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727";
        const string Netfx30RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v3.0";
        const string Netfx35RegKeyName = "Software\\Microsoft\\NET Framework Setup\\NDP\\v3.5";
        /// <summary>
        /// 4.0 Client Profile 
        /// </summary>
        const string Netfx40RegKeyNameClient = "Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client";
        /// <summary>
        /// 4.0 Full Profile 
        /// </summary>
        const string Netfx40RegKeyNameFull = "Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full";
        
        const string Netfx11PlusRegValueName = "Install";
        const string Netfx30PlusRegValueName = "InstallSuccess";
        const string Netfx11PlusSPxRegValueName = "SP";
        const string Netfx20PlusBuildRegValueName = "Increment";
        const string Netfx30PlusVersionRegValueName = "Version";
        const string Netfx35PlusBuildRegValueName = "Build";
        const string Netfx30PlusWCFRegKeyName = Netfx30RegKeyName + "\\Setup\\Windows Communication Foundation";
        const string Netfx30PlusWPFRegKeyName = Netfx30RegKeyName + "\\Setup\\Windows Presentation Foundation";
        const string Netfx30PlusWFRegKeyName = Netfx30RegKeyName + "\\Setup\\Windows Workflow Foundation";
        const string Netfx30PlusWFPlusVersionRegValueName = "FileVersion";
        const string CardSpaceServicesRegKeyName = "System\\CurrentControlSet\\Services\\idsvc";
        const string CardSpaceServicesPlusImagePathRegName = "ImagePath";

        #endregion

        #region private and internal properties and methods


        #region methods

        #region GetRegistryValue
        private static bool GetRegistryValue<T>(RegistryHive hive, string key, string value, RegistryValueKind kind, out T data)
        {
            bool success = false;
            data = default(T);

            using (RegistryKey baseKey = RegistryKey.OpenRemoteBaseKey(hive, String.Empty))
            {
                if (baseKey != null)
                {
                    using (RegistryKey registryKey = baseKey.OpenSubKey(key, RegistryKeyPermissionCheck.ReadSubTree))
                    {
                        if (registryKey != null)
                        {

                                if (registryKey != null)
                                {
                                    // If the key was opened, try to retrieve the value.
                                    object regValue = registryKey.GetValue(value, null);
                                    if (regValue != null)
                                    {
                                        RegistryValueKind kindFound = registryKey.GetValueKind(value);
                                        if (kindFound == kind)
                                        {
                                            data = (T)Convert.ChangeType(regValue, typeof(T), CultureInfo.InvariantCulture);
                                            success = true;
                                        }
                                    }
                                } 
                        }
                    }
                }
            }
            return success;
        }
        #endregion

        #region IsNetfxInstalled functions

        #region IsNetfx10Installed
        private static bool IsNetfx10Installed()
        {
            string regValue = string.Empty;
            return (GetRegistryValue(RegistryHive.LocalMachine, Netfx10RegKeyName, Netfx10RegKeyValue, RegistryValueKind.String, out regValue));
        }
        #endregion

        #region IsNetfx11Installed
        private static bool IsNetfx11Installed()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx11RegKeyName, Netfx11PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region IsNetfx20Installed
        private static bool IsNetfx20Installed()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx20RegKeyName, Netfx11PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region IsNetfx30Installed
        private static bool IsNetfx30Installed()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx30RegKeyName, Netfx11PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region IsNetfx35Installed
        private static bool IsNetfx35Installed()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx35RegKeyName, Netfx11PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region IsNetfx40ClientInstalled
        private static bool IsNetfx40ClientInstalled()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx40RegKeyNameClient, Netfx11PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region IsNetfx40FullInstalled
        private static bool IsNetfx40FullInstalled()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx40RegKeyNameFull, Netfx11PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #endregion

        #region GetNetfxSPLevel functions

        #region GetNetfx10SPLevel
        private static int GetNetfx10SPLevel()
        {
            bool foundKey = false;
            int servicePackLevel = -1;
            string regValue;

            if (IsTabletOrMediaCenter())
            {
                foundKey = GetRegistryValue(RegistryHive.LocalMachine, Netfx10SPxOCMRegKeyName, Netfx10SPxRegValueName, RegistryValueKind.String, out regValue);
            }
            else
            {
                foundKey = GetRegistryValue(RegistryHive.LocalMachine, Netfx10SPxMSIRegKeyName, Netfx10SPxRegValueName, 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 GetNetfx11SPLevel
        private static int GetNetfx11SPLevel()
        {
            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, Netfx11RegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            {
                servicePackLevel = regValue;
            }

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx20SPLevel
        private static int GetNetfx20SPLevel()
        {
            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, Netfx20RegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            {
                servicePackLevel = regValue;
            }

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx30SPLevel
        // This code is MOST LIKELY correct but will need to be verified.
        //
        // Currently, there are no service packs available for version 3.0 of 
        // the framework, so we always return -1. When a service pack does
        // become available, this method will need to be revised to correctly
        // determine the service pack level.
        private static int GetNetfx30SPLevel()
        {
            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, Netfx30RegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            {
                servicePackLevel = regValue;
            }

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx35SPLevel
        private static int GetNetfx35SPLevel()
        {
            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, Netfx35RegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            {
                servicePackLevel = regValue;
            }

            return servicePackLevel;
        }
        #endregion


        #region GetNetfx40CSPLevel
        private static int GetNetfx40CSPLevel()
        {
            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, Netfx40RegKeyNameClient, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            {
                servicePackLevel = regValue;
            }

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx40FSPLevel
        private static int GetNetfx40FSPLevel()
        {
            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, Netfx40RegKeyNameFull, Netfx11PlusSPxRegValueName, 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;

            if (IsTabletOrMediaCenter())
            {
                foundKey = GetRegistryValue(RegistryHive.LocalMachine, Netfx10SPxOCMRegKeyName, Netfx10SPxRegValueName, RegistryValueKind.String, out regValue);
            }
            else
            {
                foundKey = GetRegistryValue(RegistryHive.LocalMachine, Netfx10SPxMSIRegKeyName, Netfx10SPxRegValueName, 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, Netfx11PlusRegValueName, 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 (GetRegistryValue(RegistryHive.LocalMachine, Netfx20RegKeyName, Netfx20PlusBuildRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    // In the strict sense, we are cheating here, but the registry key name itself
                    // contains the version number.
                    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 GetNetfx30ExactVersion
        private static Version GetNetfx30ExactVersion()
        {
            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, Netfx30RegKeyName, Netfx30PlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #region GetNetfx35ExactVersion
        private static Version GetNetfx35ExactVersion()
        {
            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, Netfx35RegKeyName, Netfx30PlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #region GetNetfx40CExactVersion
        private static Version GetNetfx40CExactVersion()
        {
            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, Netfx40RegKeyNameClient, Netfx30PlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #region GetNetfx40FExactVersion
        private static Version GetNetfx40FExactVersion()
        {
            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, Netfx40RegKeyNameFull, Netfx30PlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #endregion

        #region WindowsFounationLibrary functions

        #region CardSpace

        #region IsNetfx30CardSpaceInstalled
        private static bool IsNetfx30CardSpaceInstalled()
        {
            bool found = false;
            string regValue = String.Empty;

            if (GetRegistryValue(RegistryHive.LocalMachine, CardSpaceServicesRegKeyName, CardSpaceServicesPlusImagePathRegName, RegistryValueKind.ExpandString, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region GetNetfx30CardSpaceSPLevel
        // Currently, there are no service packs available for version 3.0 of 
        // the framework, so we always return -1. When a service pack does
        // become available, this method will need to be revised to correctly
        // determine the service pack level. Based on the current method for
        // determining if CardSpace is installed, it may not be possible to
        // correctly determine the Service Pack level for CardSpace.
        private static int GetNetfx30CardSpaceSPLevel()
        {
            int servicePackLevel = -1;
            return servicePackLevel;
        }
        #endregion

        #region GetNetfx30CardSpaceExactVersion
        private static Version GetNetfx30CardSpaceExactVersion()
        {
            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, CardSpaceServicesRegKeyName, CardSpaceServicesPlusImagePathRegName, RegistryValueKind.ExpandString, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(regValue.Trim('"'));
                    int index = fileVersionInfo.FileVersion.IndexOf(' ');
                    fxVersion = new Version(fileVersionInfo.FileVersion.Substring(0, index));
                }
            }

            return fxVersion;
        }
        #endregion

        #endregion

        #region Windows Communication Foundation

        #region IsNetfx30WCFInstalled
        private static bool IsNetfx30WCFInstalled()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx30PlusWCFRegKeyName, Netfx30PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region GetNetfx30WCFSPLevel
        // This code is MOST LIKELY correct but will need to be verified.
        //
        // Currently, there are no service packs available for version 3.0 of 
        // the framework, so we always return -1. When a service pack does
        // become available, this method will need to be revised to correctly
        // determine the service pack level.
        private static int GetNetfx30WCFSPLevel()
        {
            //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, Netfx30PlusWCFRegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            //{
            //    servicePackLevel = regValue;
            //}

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx30WCFExactVersion
        private static Version GetNetfx30WCFExactVersion()
        {
            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, Netfx30PlusWCFRegKeyName, Netfx30PlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #endregion

        #region Windows Presentation Foundation

        #region IsNetfx30WPFInstalled
        private static bool IsNetfx30WPFInstalled()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx30PlusWPFRegKeyName, Netfx30PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region GetNetfx30WPFSPLevel
        // This code is MOST LIKELY correct but will need to be verified.
        //
        // Currently, there are no service packs available for version 3.0 of 
        // the framework, so we always return -1. When a service pack does
        // become available, this method will need to be revised to correctly
        // determine the service pack level.
        private static int GetNetfx30WPFSPLevel()
        {
            //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, Netfx30PlusWPFRegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            //{
            //    servicePackLevel = regValue;
            //}

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx30WPFExactVersion
        private static Version GetNetfx30WPFExactVersion()
        {
            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, Netfx30PlusWPFRegKeyName, Netfx30PlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #endregion

        #region Windows Workflow Foundation

        #region IsNetfx30WFInstalled
        private static bool IsNetfx30WFInstalled()
        {
            bool found = false;
            int regValue = 0;

            if (GetRegistryValue(RegistryHive.LocalMachine, Netfx30PlusWFRegKeyName, Netfx30PlusRegValueName, RegistryValueKind.DWord, out regValue))
            {
                if (regValue == 1)
                {
                    found = true;
                }
            }

            return found;
        }
        #endregion

        #region GetNetfx30WFSPLevel
        // This code is MOST LIKELY correct but will need to be verified.
        //
        // Currently, there are no service packs available for version 3.0 of 
        // the framework, so we always return -1. When a service pack does
        // become available, this method will need to be revised to correctly
        // determine the service pack level.
        private static int GetNetfx30WFSPLevel()
        {
            //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, Netfx30PlusWFRegKeyName, Netfx11PlusSPxRegValueName, RegistryValueKind.DWord, out regValue))
            //{
            //    servicePackLevel = regValue;
            //}

            return servicePackLevel;
        }
        #endregion

        #region GetNetfx30WFExactVersion
        private static Version GetNetfx30WFExactVersion()
        {
            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, Netfx30PlusWFRegKeyName, Netfx30PlusWFPlusVersionRegValueName, RegistryValueKind.String, out regValue))
            {
                if (!String.IsNullOrEmpty(regValue))
                {
                    fxVersion = new Version(regValue);
                }
            }

            return fxVersion;
        }
        #endregion

        #endregion

        #endregion

        #region IsTabletOrMediaCenter
        private static bool IsTabletOrMediaCenter()
        {
            return ((SafeNativeMethods.GetSystemMetrics(SystemMetric.SM_TABLETPC) != 0) || (SafeNativeMethods.GetSystemMetrics(SystemMetric.SM_MEDIACENTER) != 0));
        }
        #endregion

        #endregion

        #endregion

        #region public properties and methods

        #region methods

        #region IsInstalled

        #region IsInstalled(FrameworkVersion frameworkVersion)
        /// <summary>
        /// Determines if the specified .NET Framework version is installed
        /// on the local computer.
        /// </summary>
        /// <param name="frameworkVersion">One of the
        /// <see cref="FrameworkVersion"/> values.</param>
        /// <returns><see langword="true"/> if the specified .NET Framework
        /// version is installed; otherwise <see langword="false"/>.</returns>
        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;

                case FrameworkVersion.Fx40C:
                    ret = IsNetfx40ClientInstalled();
                    break;

                case FrameworkVersion.Fx40F:
                    ret = IsNetfx40FullInstalled();
                    break;

                default:
                    break;
            }

            return ret;
        }
        #endregion

        #region IsInstalled(WindowsFoundationLibrary foundationLibrary)
        /// <summary>
        /// Determines if the specified .NET Framework Foundation Library is
        /// installed on the local computer.
        /// </summary>
        /// <param name="foundationLibrary">One of the
        /// <see cref="WindowsFoundationLibrary"/> values.</param>
        /// <returns><see langword="true"/> if the specified .NET Framework
        /// Foundation Library is installed; otherwise <see langword="false"/>.</returns>
        public static bool IsInstalled(WindowsFoundationLibrary foundationLibrary)
        {
            bool ret = false;

            switch (foundationLibrary)
            {
                case WindowsFoundationLibrary.CardSpace:
                    ret = IsNetfx30CardSpaceInstalled();
                    break;

                case WindowsFoundationLibrary.WCF:
                    ret = IsNetfx30WCFInstalled();
                    break;

                case WindowsFoundationLibrary.WF:
                    ret = IsNetfx30WFInstalled();
                    break;

                case WindowsFoundationLibrary.WPF:
                    ret = IsNetfx30WPFInstalled();
                    break;

                default:
                    break;
            }

            return ret;
        }
        #endregion

        #endregion

        #region GetServicePackLevel

        #region GetServicePackLevel(FrameworkVersion frameworkVersion)
        /// <summary>
        /// Retrieves the service pack level for the specified .NET Framework
        /// version.
        /// </summary>
        /// <param name="frameworkVersion">One of the
        /// <see cref="FrameworkVersion"/> values.</param>
        /// <returns>An <see cref="Int32">integer</see> value representing
        /// the service pack level for the specified .NET Framework version. If
        /// the specified .NET Frameowrk version is not found, -1 is returned.
        /// </returns>
        public static int GetServicePackLevel(FrameworkVersion frameworkVersion)
        {
            int servicePackLevel = -1;

            switch (frameworkVersion)
            {
                case FrameworkVersion.Fx10:
                    servicePackLevel = GetNetfx10SPLevel();
                    break;

                case FrameworkVersion.Fx11:
                    servicePackLevel = GetNetfx11SPLevel();
                    break;

                case FrameworkVersion.Fx20:
                    servicePackLevel = GetNetfx20SPLevel();
                    break;

                case FrameworkVersion.Fx30:
                    servicePackLevel = GetNetfx30SPLevel();
                    break;

                case FrameworkVersion.Fx35:
                    servicePackLevel = GetNetfx35SPLevel();
                    break;

                case FrameworkVersion.Fx40C:
                    servicePackLevel = GetNetfx40CSPLevel();
                    break;

                case FrameworkVersion.Fx40F:
                    servicePackLevel = GetNetfx40FSPLevel();
                    break;

                default:
                    break;
            }

            return servicePackLevel;
        }
        #endregion

        #region GetServicePackLevel(WindowsFoundationLibrary foundationLibrary)
        /// <summary>
        /// Retrieves the service pack level for the specified .NET Framework
        /// Foundation Library.
        /// </summary>
        /// <param name="foundationLibrary">One of the
        /// <see cref="WindowsFoundationLibrary"/> values.</param>
        /// <returns>An <see cref="Int32">integer</see> value representing
        /// the service pack level for the specified .NET Framework Foundation
        /// Library. If the specified .NET Frameowrk Foundation Library is not
        /// found, -1 is returned.
        /// </returns>
        public static int GetServicePackLevel(WindowsFoundationLibrary foundationLibrary)
        {
            int servicePackLevel = -1;

            switch (foundationLibrary)
            {
                case WindowsFoundationLibrary.CardSpace:
                    servicePackLevel = GetNetfx30CardSpaceSPLevel();
                    break;

                case WindowsFoundationLibrary.WCF:
                    servicePackLevel = GetNetfx30WCFSPLevel();
                    break;

                case WindowsFoundationLibrary.WF:
                    servicePackLevel = GetNetfx30WFSPLevel();
                    break;

                case WindowsFoundationLibrary.WPF:
                    servicePackLevel = GetNetfx30WPFSPLevel();
                    break;

                default:
                    break;
            }

            return servicePackLevel;
        }
        #endregion

        #endregion

        #region GetExactVersion

        #region GetExactVersion(FrameworkVersion frameworkVersion)
        /// <summary>
        /// Retrieves the exact version number for the specified .NET Framework
        /// version.
        /// </summary>
        /// <param name="frameworkVersion">One of the
        /// <see cref="FrameworkVersion"/> values.</param>
        /// <returns>A <see cref="Version">version</see> representing
        /// the exact version number for the specified .NET Framework version.
        /// If the specified .NET Frameowrk version is not found, a 
        /// <see cref="Version"/> is returned that represents a 0.0.0.0 version
        /// number.
        /// </returns>
        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 = GetNetfx30ExactVersion();
                    break;

                case FrameworkVersion.Fx35:
                    fxVersion = GetNetfx35ExactVersion();
                    break;

                case FrameworkVersion.Fx40C:
                    fxVersion = GetNetfx40CExactVersion();
                    break;

                case FrameworkVersion.Fx40F:
                    fxVersion = GetNetfx40FExactVersion();
                    break;

                default:
                    break;
            }

            return fxVersion;
        }
        #endregion

        #region GetExactVersion(WindowsFoundationLibrary foundationLibrary)
        /// <summary>
        /// Retrieves the exact version number for the specified .NET Framework
        /// Foundation Library.
        /// </summary>
        /// <param name="foundationLibrary">One of the
        /// <see cref="WindowsFoundationLibrary"/> values.</param>
        /// <returns>A <see cref="Version">version</see> representing
        /// the exact version number for the specified .NET Framework Foundation
        /// Library. If the specified .NET Frameowrk Foundation Library is not
        /// found, a <see cref="Version"/> is returned that represents a 
        /// 0.0.0.0 version number.
        /// </returns>
        public static Version GetExactVersion(WindowsFoundationLibrary foundationLibrary)
        {
            Version fxVersion = new Version();

            switch (foundationLibrary)
            {
                case WindowsFoundationLibrary.CardSpace:
                    fxVersion = GetNetfx30CardSpaceExactVersion();
                    break;

                case WindowsFoundationLibrary.WCF:
                    fxVersion = GetNetfx30WCFExactVersion();
                    break;

                case WindowsFoundationLibrary.WF:
                    fxVersion = GetNetfx30WFExactVersion();
                    break;

                case WindowsFoundationLibrary.WPF:
                    fxVersion = GetNetfx30WPFExactVersion();
                    break;

                default:
                    break;
            }

            return fxVersion;
        }
        #endregion

        #endregion

        #endregion

        #endregion
    }
    #endregion
}


File form Framework. Sory I convert from c# to vb. You can change easy.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        Try
            Dim fx10Installed As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx10)
            Dim fx11Installed As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx11)
            Dim fx20Installed As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx20)
            Dim fx30Installed As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx30)
            Dim fx35Installed As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx35)
            Dim fx40CInstalled As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx40C)
            Dim fx40FInstalled As Boolean = FrameworkVersionDetection.IsInstalled(FrameworkVersion.Fx40F)

            treeView1.Nodes.Add(Environment.MachineName)
            Dim tn As TreeNode
            If fx10Installed Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 1.0"
                tn.Text = ".NET Framework 1.0"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx10).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx10).ToString)
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 1.0"
                tn.Text = ".NET Framework 1.0"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx11Installed Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 1.1"
                tn.Text = ".NET Framework 1.1"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx11).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx11))
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 1.1"
                tn.Text = ".NET Framework 1.1"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx20Installed Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 2.0"
                tn.Text = ".NET Framework 2.0"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx20).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx20))
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 2.0"
                tn.Text = ".NET Framework 2.0"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx30Installed Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 3.0"
                tn.Text = ".NET Framework 3.0"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx30).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx30))
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 3.0"
                tn.Text = ".NET Framework 3.0"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx35Installed Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 3.5"
                tn.Text = ".NET Framework 3.5"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx35).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx35))
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 3.5"
                tn.Text = ".NET Framework 3.5"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx40CInstalled Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 4.0C"
                tn.Text = ".NET Framework 4.0 Client"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx40C).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx40C))
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 4.0C"
                tn.Text = ".NET Framework 4.0 Client"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx40FInstalled Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = ".NET Framework 4.0F"
                tn.Text = ".NET Framework 4.0 Full"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(FrameworkVersion.Fx40F).ToString)
                tn.Nodes.Add("Service Pack: " & FrameworkVersionDetection.GetServicePackLevel(FrameworkVersion.Fx40F))
                treeView1.Nodes(0).Nodes.Add(tn)
            Else
                tn = New TreeNode()
                tn.ForeColor = Color.Red
                tn.Name = ".NET Framework 4.0F"
                tn.Text = ".NET Framework 4.0 Full"
                treeView1.Nodes(0).Nodes.Add(tn)
            End If
            Dim fx30PlusWCFInstalled As Boolean = FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.WCF)
            Dim fx30PlusWPFInstalled As Boolean = FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.WPF)
            Dim fx30PlusWFInstalled As Boolean = FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.WF)
            Dim fx30PlusCardSpacesInstalled As Boolean = FrameworkVersionDetection.IsInstalled(WindowsFoundationLibrary.CardSpace)


            If fx30PlusWCFInstalled Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = "WCF"
                tn.Text = "WCF"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.WCF).ToString)
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx30PlusWPFInstalled Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = "WPF"
                tn.Text = "WPF"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.WPF).ToString)
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx30PlusWFInstalled Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = "WF"
                tn.Text = "WF"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.WF).ToString)
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            If fx30PlusCardSpacesInstalled Then
                tn = New TreeNode()
                tn.ForeColor = Color.Green
                tn.Name = "Card Space"
                tn.Text = "Card Space"
                tn.Nodes.Add("Exact Version: " & FrameworkVersionDetection.GetExactVersion(WindowsFoundationLibrary.CardSpace).ToString)
                treeView1.Nodes(0).Nodes.Add(tn)
            End If

            treeView1.Nodes(0).Expand()
        Catch ex As Exception
            MessageBox.Show("Error: " & ex.Message)
        End Try
    End Sub



I hope that is helpfull
modified on Wednesday, April 27, 2011 6:34 AM

GeneralRe: Net Framewrok 4.0 Update Code [modified] Pin
MarkJoel6018-Feb-12 5:06
MarkJoel6018-Feb-12 5:06 
GeneralRe: Net Framewrok 4.0 Update Code [modified] Pin
George Hendrickson1-Feb-13 2:59
professionalGeorge Hendrickson1-Feb-13 2:59 
GeneralRe: Net Framewrok 4.0 Update Code [modified] Pin
JavierJJJ11-Feb-13 0:30
JavierJJJ11-Feb-13 0:30 
GeneralInstalledFrameworkVersions in code Pin
kiquenet.com8-Mar-11 4:02
professionalkiquenet.com8-Mar-11 4:02 
GeneralUpdate .net 4.0 - Client Profile Pin
kiquenet.com8-Mar-11 3:02
professionalkiquenet.com8-Mar-11 3:02 
QuestionUpdate for Framework 4.0?? Pin
rctaubert10-Sep-10 6:31
rctaubert10-Sep-10 6:31 
AnswerRe: Update for Framework 4.0?? Pin
Scott Dorman10-Sep-10 15:14
professionalScott Dorman10-Sep-10 15:14 
GeneralRe: Update for Framework 4.0?? Pin
kiquenet.com2-Mar-11 3:56
professionalkiquenet.com2-Mar-11 3:56 
GeneralRe: Update for Framework 4.0?? Pin
rctaubert5-Jan-12 5:44
rctaubert5-Jan-12 5:44 
AnswerRe: Update for Framework 4.0?? Pin
Marco Ensing19-Sep-10 8:30
Marco Ensing19-Sep-10 8:30 
GeneralRe: Update for Framework 4.0?? Pin
rctaubert23-Sep-10 5:23
rctaubert23-Sep-10 5:23 
GeneralRe: Update for Framework 4.0?? Pin
Scott Dorman23-Sep-10 6:35
professionalScott Dorman23-Sep-10 6:35 
GeneralRe: Update for Framework 4.0?? Pin
rctaubert23-Sep-10 8:44
rctaubert23-Sep-10 8:44 
GeneralRe: Update for Framework 4.0?? Pin
kiquenet.com8-Mar-11 2:53
professionalkiquenet.com8-Mar-11 2:53 
GeneralRun this against another machine Pin
DimondWolfe16-Oct-09 11:06
DimondWolfe16-Oct-09 11:06 
GeneralRe: Run this against another machine Pin
scot.belshaw18-Oct-09 15:09
scot.belshaw18-Oct-09 15:09 
GeneralVery practical article! Pin
DrABELL16-Sep-09 16:25
DrABELL16-Sep-09 16:25 
Question4.0 framework? Pin
nmerali26-Aug-09 4:54
nmerali26-Aug-09 4:54 
GeneralDifferent Info on Vista and XP Pin
vinodonly10-Jul-09 23:08
vinodonly10-Jul-09 23:08 
GeneralRe: Different Info on Vista and XP Pin
Scott Dorman11-Jul-09 3:31
professionalScott Dorman11-Jul-09 3:31 
GeneralRe: Different Info on Vista and XP Pin
vinodonly11-Jul-09 3:43
vinodonly11-Jul-09 3:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.