Как я могу найти версию .NET во время выполнения программно?

Мне нужно решение, чтобы предоставить мне исполняемую версию .NET как для полной структуры, так и для .NET Core.

На компьютере со следующими версиями .NET:

Full: 4.7.2
Core: 2.1.104

Продолжительность:

RuntimeInformation.FrameworkDescription

Дает мне:

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

Продолжительность:

Environment.Version

Дает мне:

Full: 4.0.30319.42000
Core: 4.0.30319.42000

Как я могу точно получить версии во время выполнения на разных платформах, зная, что параметр реестра недоступен вне Windows.

Ответ 1

Существует не единый способ сделать это еще, хотя есть открытый запрос это здесь, что вы можете отслеживать. Если вы щелкнете по различным проблемам, которые относятся к этому обсуждению, и проблемам, на которые ссылаются в дальнейшем, вы увидите, что в некоторых реализациях также есть некоторые ошибки прямо сейчас, но есть активная работа (одна из проблем имела связанную регистрацию, просто 8 часов назад).

Для .NET Framework:

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

и для .NET Core:

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

Выход:

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

Очевидно, что это немного хлопотно использовать программно, отсюда и запросы на лучший API (включая эту открытую проблему от Microsoft, обсуждающую новый API, специально ориентированный на тестирование для минимальной целевой платформы).

Другая часть головоломки, которая, вероятно, всегда будет невозможна, состоит в том, что данное приложение может ссылаться на множество целей. Например, вы можете использовать библиотеки .NET Standard 2.x и .NET Standard 1.x. Я сомневаюсь, что когда-нибудь будет хороший способ получить полную картину всех целей, стоящих за данной коллекцией исполняющих сборок...

Ответ 2

Если вы хотите узнать, какая версия .NET Framework установлена на компьютере, вам следует использовать документированный раздел реестра "Ключ выпуска". Этот ключ регистрируется в системе при установке .NET Framework.

Это публично задокументировано здесь: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/versions-and-dependencies

Вы должны написать код, который будет читать этот раздел реестра и сопоставлять его с актуальной версией .NET Framework. Вот код, который делает это для версий .NET Framework между 4.5 и 4.7.1. Вы можете дополнительно настроить это, как вам нужно. (из 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");
        }
    }

Я знаю, что вы сказали, что не хотите использовать реестр, однако я рекомендую использовать путь к реестру, если вы работаете в .NET Framework (это можно определить, посмотрев путь, по которому загружается сборка, содержащая System.Object) так как это рекомендуемый и поддерживаемый способ (мы используем то же самое в .NET Runtime, когда нам нужно проверить, какая версия установлена на машине).

Для .NET Core нет ключа реестра, который вы можете проверить. Однако вы можете использовать расположение сборки, содержащей System.Object чтобы определить версию, на которой работает ваш код.

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