Enumerating CLR versions
The following is a sample from the developer who owns mscoree.dll. The sample prints out all the CLR versions installed in the machine.
The code will be shipped in .Net framework SDK as a sample.
// This is the function pointer definition for the shim API GetRequestedRuntimeInfoInfo.
// It has existed in mscoree.dll since v1.1, and in v2.0 it was modified to take "runtimeInfoFlags"
// which allow us to get even more information.
typedef HRESULT (STDAPICALLTYPE *PGetRRI)(LPCWSTR pExe,
LPCWSTR pwszVersion,
LPCWSTR pConfigurationFile,
DWORD startupFlags,
DWORD runtimeInfoFlags,
LPWSTR pDirectory,
DWORD dwDirectory,
DWORD *dwDirectoryLength,
LPWSTR pVersion,
DWORD cchBuffer,
DWORD* dwlength);
// This is the function pointer defintion for the shim API GetCorVersion.
// It has existed in mscoree.dll since v1.0, and will display the version of the runtime that is currently
// loaded into the process. If a CLR is not loaded into the process, it will load the latest version.
typedef HRESULT (STDAPICALLTYPE *PGetCV)(LPWSTR szBuffer,
DWORD cchBuffer,
DWORD* dwLength);
//-------------------------------------------------------------
// PrintAllRuntimes
//
// This prints all of the runtimes installed on the machine
//-------------------------------------------------------------
int PrintAllRuntimes()
{
BOOL fV10installed = FALSE; // Is v1.0 installed on the machine
BOOL fV11installed = FALSE; // Is v1.1 installed on the machine
WCHAR wszLatestRuntime[30] = {0}; // Latest runtime on the machine
DWORD cchLatestRuntime = 0;
PGetRRI pfnGetRequestedRuntimeInfo = NULL;
PGetCV pfnGetCorVersion = NULL;
HMODULE hMscoree = NULL;
HRESULT hr = S_OK;
// First, if mscoree.dll is not found on the machine, then there aren't any CLRs on the machine
hMscoree = LoadLibraryA("mscoree.dll");
if (hMscoree == NULL)
goto DoneFindingRuntimes;
// There were certain OS's that shipped with a "placeholder" mscoree.dll. The existance of this DLL
// doesn't mean there are CLRs installed on the box.
//
// If this mscoree doesn't have an implementation for GetCORVersion, then we know it's one of these
// placeholder dlls.
pfnGetCorVersion = (PGetCV)GetProcAddress(hMscoree, "GetCORVersion");
if (pfnGetCorVersion == NULL)
goto DoneFindingRuntimes;
// Ok, so we now know that the CLR was, at one time, installed on this machine. Let's see what versions
// of the runtime are on the box.
// v1.0 and v1.1 had an annoying habit of popping up dialogs whenever you asked for runtimes that didn't exist.
// We'll surpress those dialogs with this statement.
SetErrorMode(SEM_FAILCRITICALERRORS);
// v1.1 of mscoree shipped with the API GetRequestedRuntimeInfo(). This function will help us with identifying
// runtimes.
pfnGetRequestedRuntimeInfo = (PGetRRI)GetProcAddress(hMscoree, "GetRequestedRuntimeInfo");
if (pfnGetRequestedRuntimeInfo == NULL)
{
// Ok, that API didn't exist. We've got the v1.0 mscoree.dll on the box. We're guaranteed that there isn't
// a later version of the CLR on the machine, but we're not 100% guaranteed that v1.0 of the CLR is on the
// box.
// Unfortuately, the only way to verify that v1.0 is on the box is to try and spin up v1.0 of the CLR and
// see if it works.
WCHAR wszVersion[50];
DWORD cchVersion = 0;
hr = pfnGetCorVersion(wszVersion, NumItems(wszVersion), &cchVersion);
// If this failed, then either the v1.0 CLR didn't exist on the machine, or, if the buffer wasn't
// big enough to copy the version information, then something is messed up on the machine (v1.0.3705 should
// fit in a 50 character buffer)
if (FAILED(hr))
goto DoneFindingRuntimes;
// If the returned string is not v1.0.3705, then this machine is messed up
if (wcscmp(wszVersion, L"v1.0.3705"))
{
printf("Installation error on this machine. v1.0 of mscoree.dll is running %S of the CLR.\n", wszVersion);
goto DoneFindingRuntimes;
}
// Ok, we've verified that v1.0 is installed.
fV10installed = TRUE;
goto DoneFindingRuntimes;
}
// Ok, we know that, at a minimum, v1.1 of mscoree is installed on the machine. That makes this job much easier.
// This function call will pop up a dialog if these runtimes don't exist on the machine, so make sure you call
// SetErrorMode(SEM_FAILCRITICALERRORS); as we did up above
WCHAR wszVersion[50]; // The version of the runtime that satisfies the runtime request
DWORD cchVersion = 0;
WCHAR wszDirectory[MAX_PATH]; // The top level directory where the runtime is located. Usually is %windir%\microsoft.net\framework
DWORD cchDirectory = 0;
// Check to see if v1.0 is installed on the machine
hr = pfnGetRequestedRuntimeInfo(NULL, // pExe
L"v1.0.3705", // pwszVersion
NULL, // ConfigurationFile
0, // startupFlags
0, // v1.1, this is reserved, in v2.0, runtimeInfoFlags
wszDirectory, // pDirectory
NumItems(wszDirectory), // dwDirectory
&cchDirectory, // dwDirectoryLength
wszVersion, // pVersion
NumItems(wszVersion), // cchBuffer
&cchVersion); // dwlength
if (SUCCEEDED(hr))
fV10installed = TRUE;
// Check to see if v1.1 is installed on the machine
hr = pfnGetRequestedRuntimeInfo(NULL, // pExe
L"v1.1.4322", // pwszVersion
NULL, // ConfigurationFile
0, // startupFlags
0, // v1.1, this is reserved, in v2.0, runtimeInfoFlags
wszDirectory, // pDirectory
NumItems(wszDirectory), // dwDirectory
&cchDirectory, // dwDirectoryLength
wszVersion, // pVersion
NumItems(wszVersion), // cchBuffer
&cchVersion); // dwlength
if (SUCCEEDED(hr))
fV11installed = TRUE;
// The same thing can be done for v2.0 when the final version number of Whidbey is decided upon.
// The v2.0 shim allows us to use flags for this function that makes it easier to use. The v1.1 mscoree.dll will
// not allow us to call this function with 3 NULLs. However, the v2.0 mscoree.dll, along with the RUNTIME_INFO_UPGRADE_VERSION
// flag, will return us the latest version of the CLR on the machine.
hr = pfnGetRequestedRuntimeInfo(NULL, // pExe
NULL, // pwszVersion
NULL, // ConfigurationFile
0, // startupFlags
RUNTIME_INFO_UPGRADE_VERSION|RUNTIME_INFO_DONT_RETURN_DIRECTORY|RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG, // runtimeInfoFlags,
NULL, // pDirectory
0, // dwDirectory
NULL, // dwDirectoryLength
wszLatestRuntime, // pVersion
NumItems(wszLatestRuntime), // cchBuffer
&cchLatestRuntime); // dwlength
// If this fails, then v2.0 of mscoree.dll was not installed on the machine.
DoneFindingRuntimes:
printf("Versions installed on the machine:\n");
if (fV10installed)
printf("v1.0.3705\n");
if (fV11installed)
printf("v1.1.4322\n");
if (*wszLatestRuntime)
printf("%S\n", wszLatestRuntime);
// If we didn't find any runtimes
if (!fV10installed && !fV11installed && !*wszLatestRuntime)
printf("<none>\n");
return 0;
}// PrintAllRuntimes