Skip to content

Instantly share code, notes, and snippets.

@augustoproiete
Created November 29, 2016 00:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save augustoproiete/f7ba6c04f1e8494cdf07ee03fb587ca6 to your computer and use it in GitHub Desktop.
Save augustoproiete/f7ba6c04f1e8494cdf07ee03fb587ca6 to your computer and use it in GitHub Desktop.
Detect .NET Framework installed on the machine (Credits: Aaron Stebner, October 24, 2016)
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <mscoree.h>
// In case the machine this is compiled on does not have the most recent platform SDK
// with these values defined, define them here
#ifndef SM_TABLETPC
#define SM_TABLETPC 86
#endif
#ifndef SM_MEDIACENTER
#define SM_MEDIACENTER 87
#endif
#define CountOf(x) sizeof(x)/sizeof(*x)
// Constants that represent registry key names and value names
// to use for detection
const TCHAR *g_szNetfx10RegKeyName = _T("Software\\Microsoft\\.NETFramework\\Policy\\v1.0");
const TCHAR *g_szNetfx10RegKeyValue = _T("3705");
const TCHAR *g_szNetfx10SPxMSIRegKeyName = _T("Software\\Microsoft\\Active Setup\\Installed Components\\{78705f0d-e8db-4b2d-8193-982bdda15ecd}");
const TCHAR *g_szNetfx10SPxOCMRegKeyName = _T("Software\\Microsoft\\Active Setup\\Installed Components\\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}");
const TCHAR *g_szNetfx11RegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322");
const TCHAR *g_szNetfx20RegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727");
const TCHAR *g_szNetfx30RegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v3.0\\Setup");
const TCHAR *g_szNetfx30SpRegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v3.0");
const TCHAR *g_szNetfx30RegValueName = _T("InstallSuccess");
const TCHAR *g_szNetfx35RegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v3.5");
const TCHAR *g_szNetfx40ClientRegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client");
const TCHAR *g_szNetfx40FullRegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full");
const TCHAR *g_szNetfx40SPxRegValueName = _T("Servicing");
const TCHAR *g_szNetfx45RegKeyName = _T("Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full");
const TCHAR *g_szNetfx45RegValueName = _T("Release");
const TCHAR *g_szNetfxStandardRegValueName = _T("Install");
const TCHAR *g_szNetfxStandardSPxRegValueName = _T("SP");
const TCHAR *g_szNetfxStandardVersionRegValueName = _T("Version");
// Version information for final release of .NET Framework 3.0
const int g_iNetfx30VersionMajor = 3;
const int g_iNetfx30VersionMinor = 0;
const int g_iNetfx30VersionBuild = 4506;
const int g_iNetfx30VersionRevision = 26;
// Version information for final release of .NET Framework 3.5
const int g_iNetfx35VersionMajor = 3;
const int g_iNetfx35VersionMinor = 5;
const int g_iNetfx35VersionBuild = 21022;
const int g_iNetfx35VersionRevision = 8;
// Version information for final release of .NET Framework 4
const int g_iNetfx40VersionMajor = 4;
const int g_iNetfx40VersionMinor = 0;
const int g_iNetfx40VersionBuild = 30319;
const int g_iNetfx40VersionRevision = 0;
// Version information for final release of .NET Framework 4.5
const int g_dwNetfx45ReleaseVersion = 378389;
// Version information for final release of .NET Framework 4.5.1
const int g_dwNetfx451ReleaseVersion = 378675;
// Version information for final release of .NET Framework 4.5.2
const int g_dwNetfx452ReleaseVersion = 379893;
// Version information for final release of .NET Framework 4.6
const int g_dwNetfx46ReleaseVersion = 393295;
// Version information for final release of .NET Framework 4.6.1
const int g_dwNetfx461ReleaseVersion = 394254;
// Version information for final release of .NET Framework 4.6.2
const int g_dwNetfx462ReleaseVersion = 394802;
// Constants for known .NET Framework versions used with the GetRequestedRuntimeInfo API
const TCHAR *g_szNetfx10VersionString = _T("v1.0.3705");
const TCHAR *g_szNetfx11VersionString = _T("v1.1.4322");
const TCHAR *g_szNetfx20VersionString = _T("v2.0.50727");
const TCHAR *g_szNetfx40VersionString = _T("v4.0.30319");
// Function prototypes
bool CheckNetfxBuildNumber(const TCHAR*, const TCHAR*, const int, const int, const int, const int);
bool CheckNetfxVersionUsingMscoree(const TCHAR*);
int GetNetfx10SPLevel();
int GetNetfxSPLevel(const TCHAR*, const TCHAR*);
DWORD GetProcessorArchitectureFlag();
bool IsCurrentOSTabletMedCenter();
bool IsNetfx10Installed();
bool IsNetfx11Installed();
bool IsNetfx20Installed();
bool IsNetfx30Installed();
bool IsNetfx35Installed();
bool IsNetfx40ClientInstalled();
bool IsNetfx40FullInstalled();
bool IsNetfx45Installed();
bool IsNetfx451Installed();
bool IsNetfx452Installed();
bool IsNetfx46Installed();
bool IsNetfx461Installed();
bool IsNetfx462Installed();
bool RegistryGetValue(HKEY, const TCHAR*, const TCHAR*, DWORD, LPBYTE, DWORD);
/******************************************************************
Function Name: CheckNetfxVersionUsingMscoree
Description: Uses the logic described in the sample code at
http://msdn2.microsoft.com/library/ydh6b3yb.aspx
to load mscoree.dll and call its APIs to determine
whether or not a specific version of the .NET
Framework is installed on the system
Inputs: pszNetfxVersionToCheck - version to look for
Results: true if the requested version is installed
false otherwise
******************************************************************/
bool CheckNetfxVersionUsingMscoree(const TCHAR *pszNetfxVersionToCheck)
{
bool bFoundRequestedNetfxVersion = false;
HRESULT hr = S_OK;
// Check input parameter
if (NULL == pszNetfxVersionToCheck)
return false;
HMODULE hmodMscoree = LoadLibraryEx(_T("mscoree.dll"), NULL, 0);
if (NULL != hmodMscoree)
{
typedef HRESULT (STDAPICALLTYPE *GETCORVERSION)(LPWSTR szBuffer, DWORD cchBuffer, DWORD* dwLength);
GETCORVERSION pfnGETCORVERSION = (GETCORVERSION)GetProcAddress(hmodMscoree, "GetCORVersion");
// Some OSs shipped with a placeholder copy of mscoree.dll. The existence of mscoree.dll
// therefore does NOT mean that a version of the .NET Framework is installed.
// If this copy of mscoree.dll does not have an exported function named GetCORVersion
// then we know it is a placeholder DLL.
if (NULL == pfnGETCORVERSION)
goto Finish;
typedef HRESULT (STDAPICALLTYPE *CORBINDTORUNTIME)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
CORBINDTORUNTIME pfnCORBINDTORUNTIME = (CORBINDTORUNTIME)GetProcAddress(hmodMscoree, "CorBindToRuntime");
typedef HRESULT (STDAPICALLTYPE *GETREQUESTEDRUNTIMEINFO)(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWSTR pConfigurationFile, DWORD startupFlags, DWORD runtimeInfoFlags, LPWSTR pDirectory, DWORD dwDirectory, DWORD *dwDirectoryLength, LPWSTR pVersion, DWORD cchBuffer, DWORD* dwlength);
GETREQUESTEDRUNTIMEINFO pfnGETREQUESTEDRUNTIMEINFO = (GETREQUESTEDRUNTIMEINFO)GetProcAddress(hmodMscoree, "GetRequestedRuntimeInfo");
if (NULL != pfnCORBINDTORUNTIME)
{
TCHAR szRetrievedVersion[50];
DWORD dwLength = CountOf(szRetrievedVersion);
if (NULL == pfnGETREQUESTEDRUNTIMEINFO)
{
// Having CorBindToRuntimeHost but not having GetRequestedRuntimeInfo means that
// this machine contains no higher than .NET Framework 1.0, but the only way to
// 100% guarantee that the .NET Framework 1.0 is installed is to call a function
// to exercise its functionality
if (0 == _tcscmp(pszNetfxVersionToCheck, g_szNetfx10VersionString))
{
hr = pfnGETCORVERSION(szRetrievedVersion, dwLength, &dwLength);
if (SUCCEEDED(hr))
{
if (0 == _tcscmp(szRetrievedVersion, g_szNetfx10VersionString))
bFoundRequestedNetfxVersion = true;
}
goto Finish;
}
}
// Set error mode to prevent the .NET Framework from displaying
// unfriendly error dialogs
UINT uOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
TCHAR szDirectory[MAX_PATH];
DWORD dwDirectoryLength = 0;
DWORD dwRuntimeInfoFlags = RUNTIME_INFO_DONT_RETURN_DIRECTORY | GetProcessorArchitectureFlag();
// Check for the requested .NET Framework version
hr = pfnGETREQUESTEDRUNTIMEINFO(NULL, pszNetfxVersionToCheck, NULL, STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST, NULL, szDirectory, CountOf(szDirectory), &dwDirectoryLength, szRetrievedVersion, CountOf(szRetrievedVersion), &dwLength);
if (SUCCEEDED(hr))
bFoundRequestedNetfxVersion = true;
// Restore the previous error mode
SetErrorMode(uOldErrorMode);
}
}
Finish:
if (hmodMscoree)
{
FreeLibrary(hmodMscoree);
}
return bFoundRequestedNetfxVersion;
}
/******************************************************************
Function Name: GetNetfx10SPLevel
Description: 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
Inputs: NONE
Results: integer representing SP level for .NET Framework 1.0
******************************************************************/
int GetNetfx10SPLevel()
{
TCHAR szRegValue[MAX_PATH];
TCHAR *pszSPLevel = NULL;
int iRetValue = -1;
bool bRegistryRetVal = false;
// Need to detect what OS we are running on so we know what
// registry key to use to look up the SP level
if (IsCurrentOSTabletMedCenter())
bRegistryRetVal = RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx10SPxOCMRegKeyName, g_szNetfxStandardVersionRegValueName, NULL, (LPBYTE)szRegValue, MAX_PATH);
else
bRegistryRetVal = RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx10SPxMSIRegKeyName, g_szNetfxStandardVersionRegValueName, NULL, (LPBYTE)szRegValue, MAX_PATH);
if (bRegistryRetVal)
{
// This registry value should be of the format
// #,#,#####,# where the last # is the SP level
// Try to parse off the last # here
pszSPLevel = _tcsrchr(szRegValue, _T(','));
if (NULL != pszSPLevel)
{
// Increment the pointer to skip the comma
pszSPLevel++;
// Convert the remaining value to an integer
iRetValue = _tstoi(pszSPLevel);
}
}
return iRetValue;
}
/******************************************************************
Function Name: GetNetfxSPLevel
Description: Determine what service pack is installed for a
version of the .NET Framework using registry
based detection methods documented in the
.NET Framework deployment guides.
Inputs: pszNetfxRegKeyName - registry key name to use for detection
pszNetfxRegValueName - registry value to use for detection
Results: integer representing SP level for .NET Framework
******************************************************************/
int GetNetfxSPLevel(const TCHAR *pszNetfxRegKeyName, const TCHAR *pszNetfxRegValueName)
{
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, pszNetfxRegKeyName, pszNetfxRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
return (int)dwRegValue;
}
// We can only get here if the .NET Framework is not
// installed or there was some kind of error retrieving
// the data from the registry
return -1;
}
/******************************************************************
Function Name: GetProcessorArchitectureFlag
Description: Determine the processor architecture of the
system (x86, x64, ia64)
Inputs: NONE
Results: DWORD processor architecture flag
******************************************************************/
DWORD GetProcessorArchitectureFlag()
{
HMODULE hmodKernel32 = NULL;
typedef void (WINAPI *PFnGetNativeSystemInfo) (LPSYSTEM_INFO);
PFnGetNativeSystemInfo pfnGetNativeSystemInfo;
SYSTEM_INFO sSystemInfo;
memset(&sSystemInfo, 0, sizeof(sSystemInfo));
bool bRetrievedSystemInfo = false;
// Attempt to load kernel32.dll
hmodKernel32 = LoadLibrary(_T("Kernel32.dll"));
if (NULL != hmodKernel32)
{
// If the DLL loaded correctly, get the proc address for GetNativeSystemInfo
pfnGetNativeSystemInfo = (PFnGetNativeSystemInfo) GetProcAddress(hmodKernel32, "GetNativeSystemInfo");
if (NULL != pfnGetNativeSystemInfo)
{
// Call GetNativeSystemInfo if it exists
(*pfnGetNativeSystemInfo)(&sSystemInfo);
bRetrievedSystemInfo = true;
}
FreeLibrary(hmodKernel32);
}
if (!bRetrievedSystemInfo)
{
// Fallback to calling GetSystemInfo if the above failed
GetSystemInfo(&sSystemInfo);
bRetrievedSystemInfo = true;
}
if (bRetrievedSystemInfo)
{
switch (sSystemInfo.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
return RUNTIME_INFO_REQUEST_X86;
case PROCESSOR_ARCHITECTURE_IA64:
return RUNTIME_INFO_REQUEST_IA64;
case PROCESSOR_ARCHITECTURE_AMD64:
return RUNTIME_INFO_REQUEST_AMD64;
default:
return 0;
}
}
return 0;
}
/******************************************************************
Function Name: CheckNetfxBuildNumber
Description: Retrieves the .NET Framework build number from
the registry and validates that it is not a pre-release
version number
Inputs: NONE
Results: true if the build number in the registry is greater
than or equal to the passed in version; false otherwise
******************************************************************/
bool CheckNetfxBuildNumber(const TCHAR *pszNetfxRegKeyName, const TCHAR *pszNetfxRegKeyValue, const int iRequestedVersionMajor, const int iRequestedVersionMinor, const int iRequestedVersionBuild, const int iRequestedVersionRevision)
{
TCHAR szRegValue[MAX_PATH];
TCHAR *pszToken = NULL;
TCHAR *pszNextToken = NULL;
int iVersionPartCounter = 0;
int iRegistryVersionMajor = 0;
int iRegistryVersionMinor = 0;
int iRegistryVersionBuild = 0;
int iRegistryVersionRevision = 0;
bool bRegistryRetVal = false;
// Attempt to retrieve the build number registry value
bRegistryRetVal = RegistryGetValue(HKEY_LOCAL_MACHINE, pszNetfxRegKeyName, pszNetfxRegKeyValue, NULL, (LPBYTE)szRegValue, MAX_PATH);
if (bRegistryRetVal)
{
// This registry value should be of the format
// #.#.#####.##. Try to parse the 4 parts of
// the version here
pszToken = _tcstok_s(szRegValue, _T("."), &pszNextToken);
while (NULL != pszToken)
{
iVersionPartCounter++;
switch (iVersionPartCounter)
{
case 1:
// Convert the major version value to an integer
iRegistryVersionMajor = _tstoi(pszToken);
break;
case 2:
// Convert the minor version value to an integer
iRegistryVersionMinor = _tstoi(pszToken);
break;
case 3:
// Convert the build number value to an integer
iRegistryVersionBuild = _tstoi(pszToken);
break;
case 4:
// Convert the revision number value to an integer
iRegistryVersionRevision = _tstoi(pszToken);
break;
default:
break;
}
// Get the next part of the version number
pszToken = _tcstok_s(NULL, _T("."), &pszNextToken);
}
}
// Compare the version number retrieved from the registry with
// the version number of the final release of the .NET Framework
// that we are checking
if (iRegistryVersionMajor > iRequestedVersionMajor)
{
return true;
}
else if (iRegistryVersionMajor == iRequestedVersionMajor)
{
if (iRegistryVersionMinor > iRequestedVersionMinor)
{
return true;
}
else if (iRegistryVersionMinor == iRequestedVersionMinor)
{
if (iRegistryVersionBuild > iRequestedVersionBuild)
{
return true;
}
else if (iRegistryVersionBuild == iRequestedVersionBuild)
{
if (iRegistryVersionRevision >= iRequestedVersionRevision)
{
return true;
}
}
}
}
// If we get here, the version in the registry must be less than the
// version of the final release of the .NET Framework we are checking,
// so return false
return false;
}
/******************************************************************
Function Name: IsCurrentOSTabletMedCenter
Description: Determine if the current OS is a Windows XP
Tablet PC Edition or Windows XP Media Center
Edition system
Inputs: NONE
Results: true if the OS is Tablet PC or Media Center
false otherwise
******************************************************************/
bool IsCurrentOSTabletMedCenter()
{
// Use GetSystemMetrics to detect if we are on a Tablet PC or Media Center OS
return ( (GetSystemMetrics(SM_TABLETPC) != 0) || (GetSystemMetrics(SM_MEDIACENTER) != 0) );
}
/******************************************************************
Function Name: IsNetfx10Installed
Description: 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
Inputs: NONE
Results: true if the .NET Framework 1.0 is installed
false otherwise
******************************************************************/
bool IsNetfx10Installed()
{
TCHAR szRegValue[MAX_PATH];
return (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx10RegKeyName, g_szNetfx10RegKeyValue, NULL, (LPBYTE)szRegValue, MAX_PATH));
}
/******************************************************************
Function Name: IsNetfx11Installed
Description: 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
Inputs: NONE
Results: true if the .NET Framework 1.1 is installed
false otherwise
******************************************************************/
bool IsNetfx11Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx11RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx20Installed
Description: Uses the detection method recommended at
http://msdn2.microsoft.com/library/aa480243.aspx
to determine whether the .NET Framework 2.0 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 2.0 is installed
false otherwise
******************************************************************/
bool IsNetfx20Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx20RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx30Installed
Description: 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
Inputs: NONE
Results: true if the .NET Framework 3.0 is installed
false otherwise
******************************************************************/
bool IsNetfx30Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
// Check that the InstallSuccess registry value exists and equals 1
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx30RegKeyName, g_szNetfx30RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
// A system with a pre-release version of the .NET Framework 3.0 can
// have the InstallSuccess value. As an added verification, check the
// version number listed in the registry
return (bRetValue && CheckNetfxBuildNumber(g_szNetfx30RegKeyName, g_szNetfxStandardVersionRegValueName, g_iNetfx30VersionMajor, g_iNetfx30VersionMinor, g_iNetfx30VersionBuild, g_iNetfx30VersionRevision));
}
/******************************************************************
Function Name: IsNetfx35Installed
Description: 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
Inputs: NONE
Results: true if the .NET Framework 3.5 is installed
false otherwise
******************************************************************/
bool IsNetfx35Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
// Check that the Install registry value exists and equals 1
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx35RegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
// A system with a pre-release version of the .NET Framework 3.5 can
// have the Install value. As an added verification, check the
// version number listed in the registry
return (bRetValue && CheckNetfxBuildNumber(g_szNetfx35RegKeyName, g_szNetfxStandardVersionRegValueName, g_iNetfx35VersionMajor, g_iNetfx35VersionMinor, g_iNetfx35VersionBuild, g_iNetfx35VersionRevision));
}
/******************************************************************
Function Name: IsNetfx40ClientInstalled
Description: Uses the detection method recommended at
http://msdn.microsoft.com/library/ee942965(v=VS.100).aspx
to determine whether the .NET Framework 4 Client is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4 Client is installed
false otherwise
******************************************************************/
bool IsNetfx40ClientInstalled()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx40ClientRegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
// A system with a pre-release version of the .NET Framework 4 can
// have the Install value. As an added verification, check the
// version number listed in the registry
return (bRetValue && CheckNetfxBuildNumber(g_szNetfx40ClientRegKeyName, g_szNetfxStandardVersionRegValueName, g_iNetfx40VersionMajor, g_iNetfx40VersionMinor, g_iNetfx40VersionBuild, g_iNetfx40VersionRevision));
}
/******************************************************************
Function Name: IsNetfx40FullInstalled
Description: Uses the detection method recommended at
http://msdn.microsoft.com/library/ee942965(v=VS.100).aspx
to determine whether the .NET Framework 4 Full is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4 Full is installed
false otherwise
******************************************************************/
bool IsNetfx40FullInstalled()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx40FullRegKeyName, g_szNetfxStandardRegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (1 == dwRegValue)
bRetValue = true;
}
// A system with a pre-release version of the .NET Framework 4 can
// have the Install value. As an added verification, check the
// version number listed in the registry
return (bRetValue && CheckNetfxBuildNumber(g_szNetfx40FullRegKeyName, g_szNetfxStandardVersionRegValueName, g_iNetfx40VersionMajor, g_iNetfx40VersionMinor, g_iNetfx40VersionBuild, g_iNetfx40VersionRevision));
}
/******************************************************************
Function Name: IsNetfx45Installed
Description: Uses the detection method recommended at
http://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx
to determine whether the .NET Framework 4.5 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4.5 is installed
false otherwise
******************************************************************/
bool IsNetfx45Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (g_dwNetfx45ReleaseVersion <= dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx451Installed
Description: Uses the detection method recommended at
http://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx
to determine whether the .NET Framework 4.5.1 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4.5.1 is installed
false otherwise
******************************************************************/
bool IsNetfx451Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (g_dwNetfx451ReleaseVersion <= dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx452Installed
Description: Uses the detection method recommended at
http://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx
to determine whether the .NET Framework 4.5.2 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4.5.2 is installed
false otherwise
******************************************************************/
bool IsNetfx452Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (g_dwNetfx452ReleaseVersion <= dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx46Installed
Description: Uses the detection method recommended at
http://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx
to determine whether the .NET Framework 4.6 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4.6 is installed
false otherwise
******************************************************************/
bool IsNetfx46Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (g_dwNetfx46ReleaseVersion <= dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx461Installed
Description: Uses the detection method recommended at
http://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx
to determine whether the .NET Framework 4.6.1 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4.6.1 is installed
false otherwise
******************************************************************/
bool IsNetfx461Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (g_dwNetfx461ReleaseVersion <= dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: IsNetfx462Installed
Description: Uses the detection method recommended at
http://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx
to determine whether the .NET Framework 4.6.2 is
installed on the machine
Inputs: NONE
Results: true if the .NET Framework 4.6.2 is installed
false otherwise
******************************************************************/
bool IsNetfx462Installed()
{
bool bRetValue = false;
DWORD dwRegValue=0;
if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD)))
{
if (g_dwNetfx462ReleaseVersion <= dwRegValue)
bRetValue = true;
}
return bRetValue;
}
/******************************************************************
Function Name: RegistryGetValue
Description: Get the value of a reg key
Inputs: HKEY hk - The hk of the key to retrieve
TCHAR *pszKey - Name of the key to retrieve
TCHAR *pszValue - The value that will be retrieved
DWORD dwType - The type of the value that will be retrieved
LPBYTE data - A buffer to save the retrieved data
DWORD dwSize - The size of the data retrieved
Results: true if successful, false otherwise
******************************************************************/
bool RegistryGetValue(HKEY hk, const TCHAR * pszKey, const TCHAR * pszValue, DWORD dwType, LPBYTE data, DWORD dwSize)
{
HKEY hkOpened;
// Try to open the key
if (RegOpenKeyEx(hk, pszKey, 0, KEY_READ, &hkOpened) != ERROR_SUCCESS)
{
return false;
}
// If the key was opened, try to retrieve the value
if (RegQueryValueEx(hkOpened, pszValue, 0, &dwType, (LPBYTE)data, &dwSize) != ERROR_SUCCESS)
{
RegCloseKey(hkOpened);
return false;
}
// Clean up
RegCloseKey(hkOpened);
return true;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
int iNetfx10SPLevel = -1;
int iNetfx11SPLevel = -1;
int iNetfx20SPLevel = -1;
int iNetfx30SPLevel = -1;
int iNetfx35SPLevel = -1;
int iNetfx40ClientSPLevel = -1;
int iNetfx40FullSPLevel = -1;
int iNetfx45SPLevel = -1;
int iNetfx451SPLevel = -1;
int iNetfx452SPLevel = -1;
int iNetfx46SPLevel = -1;
int iNetfx461SPLevel = -1;
int iNetfx462SPLevel = -1;
TCHAR szMessage[MAX_PATH];
TCHAR szOutputString[MAX_PATH*20];
// Determine whether or not the .NET Framework
// 1.0, 1.1, 2.0, 3.0, 3.5, 4, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, or 4.6.2 are installed
bool bNetfx10Installed = (IsNetfx10Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx10VersionString));
bool bNetfx11Installed = (IsNetfx11Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx11VersionString));
bool bNetfx20Installed = (IsNetfx20Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx20VersionString));
// The .NET Framework 3.0 is an add-in that installs
// on top of the .NET Framework 2.0. For this version
// check, validate that both 2.0 and 3.0 are installed.
bool bNetfx30Installed = (IsNetfx20Installed() && IsNetfx30Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx20VersionString));
// The .NET Framework 3.5 is an add-in that installs
// on top of the .NET Framework 2.0 and 3.0. For this version
// check, validate that 2.0, 3.0 and 3.5 are installed.
bool bNetfx35Installed = (IsNetfx20Installed() && IsNetfx30Installed() && IsNetfx35Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx20VersionString));
bool bNetfx40ClientInstalled = (IsNetfx40ClientInstalled() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
bool bNetfx40FullInstalled = (IsNetfx40FullInstalled() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
// The .NET Framework 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, and 4.6.2 are in-place replacements for the .NET Framework 4.
// They use the same runtime version as the .NET Framework 4.
bool bNetfx45Installed = (IsNetfx45Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
bool bNetfx451Installed = (IsNetfx451Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
bool bNetfx452Installed = (IsNetfx452Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
bool bNetfx46Installed = (IsNetfx46Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
bool bNetfx461Installed = (IsNetfx461Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
bool bNetfx462Installed = (IsNetfx462Installed() && CheckNetfxVersionUsingMscoree(g_szNetfx40VersionString));
// If .NET Framework 1.0 is installed, get the
// service pack level
if (bNetfx10Installed)
{
iNetfx10SPLevel = GetNetfx10SPLevel();
if (iNetfx10SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T(".NET Framework 1.0 service pack %i is installed."), iNetfx10SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T(".NET Framework 1.0 is installed with no service packs."));
_tcscpy_s(szOutputString, szMessage);
}
else
{
_tcscpy_s(szOutputString, _T(".NET Framework 1.0 is not installed."));
}
// If .NET Framework 1.1 is installed, get the
// service pack level
if (bNetfx11Installed)
{
iNetfx11SPLevel = GetNetfxSPLevel(g_szNetfx11RegKeyName, g_szNetfxStandardSPxRegValueName);
if (iNetfx11SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 1.1 service pack %i is installed."), iNetfx11SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 1.1 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 1.1 is not installed."));
}
// If .NET Framework 2.0 is installed, get the
// service pack level
if (bNetfx20Installed)
{
iNetfx20SPLevel = GetNetfxSPLevel(g_szNetfx20RegKeyName, g_szNetfxStandardSPxRegValueName);
if (iNetfx20SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 2.0 service pack %i is installed."), iNetfx20SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 2.0 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 2.0 is not installed."));
}
// If .NET Framework 3.0 is installed, get the
// service pack level
if (bNetfx30Installed)
{
iNetfx30SPLevel = GetNetfxSPLevel(g_szNetfx30SpRegKeyName, g_szNetfxStandardSPxRegValueName);
if (iNetfx30SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 3.0 service pack %i is installed."), iNetfx30SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 3.0 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 3.0 is not installed."));
}
// If .NET Framework 3.5 is installed, get the
// service pack level
if (bNetfx35Installed)
{
iNetfx35SPLevel = GetNetfxSPLevel(g_szNetfx35RegKeyName, g_szNetfxStandardSPxRegValueName);
if (iNetfx35SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 3.5 service pack %i is installed."), iNetfx35SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 3.5 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 3.5 is not installed."));
}
// If .NET Framework 4 Client is installed, get the
// service pack level
if (bNetfx40ClientInstalled)
{
iNetfx40ClientSPLevel = GetNetfxSPLevel(g_szNetfx40ClientRegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx40ClientSPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4 client service pack %i is installed."), iNetfx40ClientSPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4 client is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4 client is not installed."));
}
// If .NET Framework 4 Full is installed, get the
// service pack level
if (bNetfx40FullInstalled)
{
iNetfx40FullSPLevel = GetNetfxSPLevel(g_szNetfx40FullRegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx40FullSPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4 full service pack %i is installed."), iNetfx40FullSPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4 full is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4 full is not installed."));
}
// If .NET Framework 4.5 is installed, get the
// service pack level
if (bNetfx45Installed)
{
iNetfx45SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx45SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.5 service pack %i is installed."), iNetfx45SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.5 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4.5 is not installed."));
}
// If .NET Framework 4.5.1 is installed, get the
// service pack level
if (bNetfx451Installed)
{
iNetfx451SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx451SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.5.1 service pack %i is installed."), iNetfx451SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.5.1 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4.5.1 is not installed."));
}
// If .NET Framework 4.5.2 is installed, get the
// service pack level
if (bNetfx452Installed)
{
iNetfx452SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx452SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.5.2 service pack %i is installed."), iNetfx452SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.5.2 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4.5.2 is not installed."));
}
// If .NET Framework 4.6 is installed, get the
// service pack level
if (bNetfx46Installed)
{
iNetfx46SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx46SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.6 service pack %i is installed."), iNetfx46SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.6 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4.6 is not installed."));
}
// If .NET Framework 4.6.1 is installed, get the
// service pack level
if (bNetfx461Installed)
{
iNetfx461SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx461SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.6.1 service pack %i is installed."), iNetfx461SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.6.1 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4.6.1 is not installed."));
}
// If .NET Framework 4.6.2 is installed, get the
// service pack level
if (bNetfx462Installed)
{
iNetfx462SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName);
if (iNetfx462SPLevel > 0)
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.6.2 service pack %i is installed."), iNetfx462SPLevel);
else
_stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.6.2 is installed with no service packs."));
_tcscat_s(szOutputString, szMessage);
}
else
{
_tcscat_s(szOutputString, _T("\n\n.NET Framework 4.6.2 is not installed."));
}
MessageBox(NULL, szOutputString, _T(".NET Framework Install Info"), MB_OK | MB_ICONINFORMATION);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment