How can I find the version of .NET run-time programmatically?

There isn't a unified way to do this yet, although there is an open request for this here that you can track. If you click through the various issues that reference that discussion and the issues referenced further downstream, you'll see there are also some bugs in some implementations right now, but there is active work (one of the issues had a related check-in just 8 hours ago).

For .NET Framework:

using System;
...
string ver = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;

and for .NET Core:

using System.Reflection;
using System.Runtime.Versioning;
...
string ver = Assembly.GetEntryAssembly()?.GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;

Output:

.NETFramework,Version=v4.5.1
.NETCoreApp,Version=v2.0

Obviously these are a bit of a hassle to use programmatically, hence the requests for a better API (including this open issue from Microsoft discussing a new API specifically focused on testing for a minimum target framework).

The other piece of the puzzle that will probably always be impossible is that a given application can reference many targets. Under the hood you might be pulling in .NET Standard 2.x and .NET Standard 1.x libraries, for example. I doubt there will ever be a good way to get a complete picture of all the targets behind a given collection of executing assemblies...


If you want to know which version of .NET Framework is installed on a machine you should use the documented 'Release Key' Registry Key. That key is registered in the system when .NET Framework is installed.

This is publicly documented here: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/versions-and-dependencies

You have to write the code that will read that registry key and map it to an actual .NET Framework version. Here is code that does that for .NET Framework versions betwee 4.5 and 4.7.1. You can further customize that as you need to. (from https://github.com/dotnet/corefx/blob/master/src/CoreFx.Private.TestUtilities/src/System/PlatformDetection.NetFx.cs#L33)

    private static Version GetFrameworkVersion()
    {
        using (RegistryKey ndpKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"))
        {
            if (ndpKey != null)
            {
                int value = (int)(ndpKey.GetValue("Release") ?? 0);
                if (value >= 528040) 
                    return new Version(4, 8, 0);

                if (value >= 461808) 
                    return new Version(4, 7, 2);

                if (value >= 461308)
                    return new Version(4, 7, 1);

                if (value >= 460798)
                    return new Version(4, 7, 0);

                if (value >= 394802)
                    return new Version(4, 6, 2);

                if (value >= 394254)
                    return new Version(4, 6, 1);

                if (value >= 393295)
                    return new Version(4, 6, 0);

                if (value >= 379893)
                    return new Version(4, 5, 2);

                if (value >= 378675)
                    return new Version(4, 5, 1);

                if (value >= 378389)
                    return new Version(4, 5, 0);

                throw new NotSupportedException($"No 4.5 or later framework version detected, framework key value: {value}");
            }

            throw new NotSupportedException(@"No registry key found under 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' to determine running framework version");
        }
    }

I know you said that you don't want to use the registry, however I recommend you use the registry path if you are running on .NET Framework (you can detect that by looking at the path where assembly containing System.Object is loaded from) as that is the recommended and supported way (we use the same inside the .NET Runtime when we need to check what version is installed on a machine).

For .NET Core there isn't a registry key you can check. However, you can use the location of the assembly that contains System.Object to identify the version on which your code is running on.

    public static Version GetVersion()
    {
        string runtimePath = System.IO.Path.GetDirectoryName(typeof(object).Assembly.Location);
        // Making the assumption that the path looks like this
        // C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.0.6
        string version = runtimePath.Substring(runtimePath.LastIndexOf('\\') + 1);

        return new Version(version);
    }

I faced a similar problem, for Inno Setup, I needed to find out if NET Core was installed and if so which version? Using the registry is not the way. For this reason, I reading console outputs:

    /// <summary>
    /// Detect installed NET Core version (major).
    /// The method for .NET Framework applications and library when you need to know are the NETCore application running is possible 
    /// For NETCore application simple use Environment.Version Property
    /// </summary>
    /// <returns>
    /// NET Core version or error code:
    /// -1: some exception
    /// -2: not installed or wrong dotnet prompt
    /// -3: access file system problems
    /// </returns>
    [DllExport("GetNETCoreVersion", CallingConvention = CallingConvention.StdCall)]
    public static int GetNETCoreVersion()
    {
        try
        {
            //we need create and run .cmd file to make console output redirection to file with using ">" operator (OLD GOOD MS DOS)
            string cmdFileName = Path.GetTempFileName() + ".cmd";
            string versionFileName = Path.GetTempFileName();

            //like: cmd dotnet --version with console output redirection to file "versionFileName"
            //full command id: cmd dotnet --version >> "versionFileName"                
            File.WriteAllText(cmdFileName, "dotnet --version > " + versionFileName);

            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
            {
                WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
                WorkingDirectory = Path.GetDirectoryName(cmdFileName),
                FileName = cmdFileName
            };

            System.Diagnostics.Process process = new System.Diagnostics.Process
            {
                StartInfo = startInfo
            };
            process.Start();
            process.WaitForExit();

            //after success dotnet --version >> "tempFileName", the "tempFileName" file must be exists and contains NET Core version 
            if (File.Exists(versionFileName))
            {
                string versionsinfo = File.ReadAllText(versionFileName);
                File.Delete(versionsinfo);
                //only major version is interested
                versionsinfo = versionsinfo.Substring(0, versionsinfo.IndexOf("."));
                int version = -2;
                int.TryParse(versionsinfo, out version);
                return version;
            }
            return -3;
        }
        catch
        {
            return -1;
        }
    }

Tags:

C#

.Net

.Net Core