Question

As the title says: Is there a common way in C# and especially unmanaged native C++ to determine installed CLR versions? This means not just checking whether the Framework is installed according this KB article. I want to do it by using the CLR interface, as done here for CLR1, CLR1.1 and CLR2. In this way I can make sure that they are really installed. But this doesn't apply to CLR4. Any Ideas?

My goal is to create an enumeration of available CLR versions like Clrver (regardless the process list functionallity) does.

Was it helpful?

Solution

"Common way" or not, but dotNetInstaller at Codeplex does this in native, unmanaged C++ code.
SInce it's open source, take a look how they do it.

Further, you can use the ICLRMetaHost::EnumerateInstalledRuntimes Method to detect .NET v4+ and GetRequestedRuntimeInfoInfo (much the same way as clrver.cpp does it) to detect .NET v1 - v2. So you have to make two calls, but that should cover it.

OTHER TIPS

While reading Jeffrey Richters book Applied Microsoft® .NET Framework Programming I've found some interesting hints towards that topic. Towards the topic Loading the Common Language Runtime (p. 41) he mentioned to examine the registry path (and subkeys) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\policy to check for installed runtimes. Therefore I've found an interesting KB article towards that topic. Furthermore in the section How the Runtime Resolves Type References (p. 132) he mentioned that mscorlib.dll is tied to the CLR version. So i think it should be possible to check the found registry keys against this file and its version to ensure that the found key is installed CLR version.

In the following you will find my conclusion about that in code. :) I think Clrver does something similar. And I think this solution should be also applicable for a native C++ application since my following code is C# and is just using very basic framework functions.

List<string> installedRuntimes = new List<string>();

Regex rxVersion = new Regex(@"^[v](\d{1,5})([\.](\d{1,5})){0,3}$");
Regex rxVersionPart = new Regex(@"^\d{1,5}$");            

try
{
    string installPath = Convert.ToString(Registry.GetKey("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework").GetValue("InstallRoot"));
    string[] shortVersions = Registry.GetKey("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework/Policy", false).GetSubKeyNames();
    foreach (string shortVersion in shortVersions)
        if (rxVersion.IsMatch(shortVersion))
        {
            string[] versionExtensions = Registry.GetKey("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework/Policy/" + shortVersion, false).GetValueNames();
            foreach (string versionExtension in versionExtensions)
                if (rxVersionPart.IsMatch(versionExtension))
                {
                    string fullVersion = shortVersion + "." + versionExtension;
                    if (rxVersion.IsMatch(fullVersion))
                    {
                        string clrPath = installPath + fullVersion + "\\mscorlib.dll";
                        if (File.Exists(clrPath) && FileVersionInfo.GetVersionInfo(clrPath).FileVersion.StartsWith(fullVersion.Substring(1))) installedRuntimes.Add(fullVersion);
                    }
                }
        }
}
catch { } // May fails while getting a specific registry key, if Microsoft changes the naming rules.

(Don't mess up with Registry.GetKey(...) - its just a wrapper for the .NET Registry functionality, to easify it towards the way I am used to use the registry.) In the end you should have the CLR version strings inside the list installedRuntimes as Clrver lists it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top