#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; // Version information for final release of .NET Framework 4.7 const int g_dwNetfx47ReleaseVersion = 460798; // 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 IsNetfx47Installed(); 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: IsNetfx47Installed Description: Uses the detection method recommended at https://msdn.microsoft.com/en-us/library/ee942965(v=vs.110).aspx to determine whether the .NET Framework 4.7 is installed on the machine Inputs: NONE Results: true if the .NET Framework 4.7 is installed false otherwise ******************************************************************/ bool IsNetfx47Installed() { bool bRetValue = false; DWORD dwRegValue = 0; if (RegistryGetValue(HKEY_LOCAL_MACHINE, g_szNetfx45RegKeyName, g_szNetfx45RegValueName, NULL, (LPBYTE)&dwRegValue, sizeof(DWORD))) { if (g_dwNetfx47ReleaseVersion <= 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; int iNetfx47SPLevel = -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, 4.6.2 or 4.7 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, 4.6.2 and 4.7 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)); bool bNetfx47Installed = (IsNetfx47Installed() && 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.")); } // If .NET Framework 4.7 is installed, get the service pack level if (bNetfx47Installed) { iNetfx47SPLevel = GetNetfxSPLevel(g_szNetfx45RegKeyName, g_szNetfx40SPxRegValueName); if (iNetfx47SPLevel > 0) _stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.7 service pack %i is installed."), iNetfx47SPLevel); else _stprintf_s(szMessage, MAX_PATH, _T("\n\n.NET Framework 4.7 is installed with no service packs.")); _tcscat_s(szOutputString, szMessage); } else { _tcscat_s(szOutputString, _T("\n\n.NET Framework 4.7 is not installed.")); } MessageBox(NULL, szOutputString, _T(".NET Framework Install Info"), MB_OK | MB_ICONINFORMATION); return 0; }
[VC++] .NET 버전 체크
2017. 9. 4. 10:23