-1

I've read various posts about determining the .NET Framework versions installed by checking registry entries. But I read in this article that different .NET Framework versions require different CLR versions on which to run. So I know, from the registry, that I have .NET Framework 4.8 installed on my Dev server. And I've run clrver.exe and determined that I have CLR version 4.0.30319 installed, which will only support up to .NET Framework v4.5.2. That's all on my Dev server. I want to konw the same information for my Test and Production servers. I can get the .NET Framework versions from the registry, but how can I determine the CLR version on a machine that doesn't have Visual Studio installed, since clrver.exe is a Visual Studio tool?

Zoe
  • 856
  • 1
  • 9
  • 22
  • 1
    You can check it using powershell as it`s described [here](https://stackoverflow.com/questions/3344855/which-net-version-is-my-powershell-script-using) – Pavel Anikhouski Jul 12 '19 at 18:49
  • As long as it is .NET Framework 4.x, the CLR version is 4.0.30319. Microsoft did not change that for years, for backward compatibilities. – Lex Li Jul 12 '19 at 21:05
  • According to the article referenced in my original post, whether or not the CLR supports .NET Framework 4.5.2 or 4.6 and higher depends on a fourth component of the CLR version. "CLR version 4.0.30319.xxxxx supports .NET Framework versions 4 through 4.5.2, where xxxxx is less than 42000, and CLR version 4.0.30319.42000 supports .NET Framework versions starting with .NET Framework 4.6." Clrver.exe doesn't supply that component of the CLR version, but the Powershell solution from @PavelAnikhouski above does. If it were an answer instead of a comment, I'd mark it as the answer. – Zoe Jul 15 '19 at 11:56

1 Answers1

-1

clrver.exe calls CLRCreateInstance

So you can do the same thing =>

I get :

Version: v2.0.50727

Version: v4.0.30319

object pCLRMetaHost;
HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, typeof(ICLRMetaHost).GUID, out pCLRMetaHost);
if (hr == HRESULT.S_OK)
{
    ICLRMetaHost CLRMetaHost = (ICLRMetaHost)pCLRMetaHost;
    IEnumUnknown pEnumUnknown;
    hr = CLRMetaHost.EnumerateInstalledRuntimes(out pEnumUnknown);
    if (hr == HRESULT.S_OK)
    {
        object[] pUnknown = new object[1];
        uint uceltFetched;
        while (HRESULT.S_OK == pEnumUnknown.Next(1, pUnknown, out uceltFetched) && (uceltFetched == 1))
        {
            int nBufferSize = 256;
            StringBuilder sbBuffer = new StringBuilder(nBufferSize);
            ICLRRuntimeInfo CLRRuntimeInfo = (ICLRRuntimeInfo)pUnknown[0];
            CLRRuntimeInfo.GetVersionString(sbBuffer, ref nBufferSize);
            Console.WriteLine("Version: {0}", sbBuffer);
        }
    }
    Marshal.ReleaseComObject(pCLRMetaHost);
}

with declarations :

    public enum HRESULT : int
    {
        S_OK = 0,
        S_FALSE = 1,
        E_NOINTERFACE = unchecked((int)0x80004002),
        E_NOTIMPL = unchecked((int)0x80004001),
        E_FAIL = unchecked((int)0x80004005),
    }

    [ComImport]
    [Guid("D332DB9E-B9B3-4125-8207-A14884F53216")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICLRMetaHost
    {
        HRESULT GetRuntime(string pwzVersion, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppRuntime) ;
        HRESULT GetVersionFromFile(string pwzFilePath, StringBuilder pwzBuffer, ref uint pcchBuffer);
        HRESULT EnumerateInstalledRuntimes(out IEnumUnknown ppEnumerator);
        HRESULT EnumerateLoadedRuntimes(IntPtr hndProcess, out IEnumUnknown ppEnumerator);
        HRESULT RequestRuntimeLoadedNotification(IntPtr pCallbackFunction);
        HRESULT QueryLegacyV2RuntimeBinding([In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk);
        HRESULT ExitProcess(int iExitCode);
    }

    [Guid("00000100-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IEnumUnknown
    {
        HRESULT Next([In, MarshalAs(UnmanagedType.U4)] uint celt, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.IUnknown, SizeParamIndex = 0)] object[] rgelt,
            [MarshalAs(UnmanagedType.U4)] out uint pceltFetched);
        HRESULT Skip(uint celt);
        HRESULT Reset();
        HRESULT Clone(out IEnumUnknown ppenum);
    }

    [Guid("BD39D1D2-BA2F-486a-89B0-B4B0CB466891")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ICLRRuntimeInfo
    {
        HRESULT GetVersionString(StringBuilder pwzBuffer, ref int pcchBuffer);
        HRESULT GetRuntimeDirectory(StringBuilder pwzBuffer, ref int pcchBuffer);
        HRESULT IsLoaded(IntPtr hndProcess, out bool pbLoaded);
        HRESULT LoadErrorString(uint iResourceID, StringBuilder pwzBuffer, out int pcchBuffer, int iLocaleID);
        HRESULT LoadLibrary(string pwzDllName, out IntPtr phndModule);
        HRESULT GetProcAddress(string pszProcName, out IntPtr ppProc);
        HRESULT GetInterface([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk);
        HRESULT IsLoadable(out bool pbLoadable);
        HRESULT SetDefaultStartupFlags(int dwStartupFlags, string pwzHostConfigFile);
        HRESULT GetDefaultStartupFlags(out int pdwStartupFlags, StringBuilder pwzHostConfigFile, ref int pcchHostConfigFile);
        HRESULT BindAsLegacyV2Runtime();
        HRESULT IsStarted(out bool pbStarted, out int pdwStartupFlags);
    }

    [DllImport("MSCorEE.dll", SetLastError = true)]
    public static extern HRESULT CLRCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out object ppInterface);

    static Guid CLSID_CLRMetaHost = new Guid("{9280188d-0e8e-4867-b30c-7fa83884e8de}");
Castorix
  • 1,465
  • 1
  • 9
  • 11