MaYaN
MaYaN

Reputation: 7006

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

I need a solution to give me the .NET run-time version of both the full framework as well as the .NET Core.

On a machine with the following .NET versions:

Full: 4.7.2
Core: 2.1.104

Running:

RuntimeInformation.FrameworkDescription

Gives me:

Full: .NET Framework 4.7.2558.0
Core: .NET Core 4.6.26212.01

Running:

Environment.Version

Gives me:

Full: 4.0.30319.42000
Core: 4.0.30319.42000

How can I accurately get the run-time versions across different platforms knowing that the registry option is not available outside Windows.

Upvotes: 36

Views: 26758

Answers (4)

McGuireV10
McGuireV10

Reputation: 9946

Ideally you should not care too much about the version of .NET you are running on. There are better techniques like using reflection to check for features or by using self-contained deployment to completely control the version of .NET included with your application.

Library authors targeting .NET Standard however often need to customize behavior depending on which type of .NET try are running on.

Detecting the version of modern .NET

If you are targeting .NET Core 3.0 or later (and to be clear, this also applies if you are targeting .NET 5 and later), the answer is very simple: Environment.Version returns the version of the .NET runtime and RuntimeInformation.FrameworkDescription returns a textual description like .NET Core 3.1.32 or .NET 7.0.12. See this breaking change notice that describes this behavior.

If you are targeting earlier versions of .NET Core or the .NET Framework, the story is more complicated.

Detecting different types of .NET

If you merely want to differentiate between .NET Framework and .NET (nee .NET Core), you can use the RuntimeInformation.FrameworkDescription property. For example, if you are just trying to figure out whether your should dynamically load an assembly for .NET or .NET Framework, this property should be enough. It exists on every version of .NET Core (and .NET), so if the property does not exist your are probably running on an older version of .NET Framework.

You can do something like this:

using System.Runtime.InteropServices;

Assembly a;
if (RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework"))
{
    a = Assembly.LoadFile("netfx/MyAssembly.dll");
}
else
{
    a = Assembly.LoadFile("netcore/MyAssembly.dll");
}

Older frameworks

If you are running on .NET Framework and really need to know version, you will have to use the registry method. Note that .NET Framework looks are the target framework of your application and changes its behavior to preserve backwards compatibility, so there are limits to this approach.

If you are trying to detect the exact version of .NET Core prior to 3.0, there are not any good answers that I know of. If you are in a framework-dependant application, you can look at location of system assembly and parse out a version from. For example, this:

Console.WriteLine(typeof(object).Assembly.Location)

prints this when running on my machine:

C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.8\System.Private.CoreLib.dll

You can see the version in the file path, but I don't think this is a reliable way to detect the version. For example, this would not work in a self-contained .NET Core app.

Upvotes: 45

Hamed Vahedi
Hamed Vahedi

Reputation: 49

The most appropriate way is:

string installedVersion = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName; //for .NET Framework:

string installedVersion = Assembly.GetEntryAssembly()?.GetCustomAttribute()?.FrameworkName; //for .NET Core:

But to call the "TargetFrameworkName" method, it is necessary to have at least version 4.5 installed. So, it is recommended to use the alternative way in an older version that has been tested in my case:

Version installedVersion = Environment.Version;

Upvotes: 1

Denis Kirin
Denis Kirin

Reputation: 11

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;
        }
    }

Upvotes: 1

Alex Ghiondea - MSFT
Alex Ghiondea - MSFT

Reputation: 3380

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://learn.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);
    }

Upvotes: 10

Related Questions