Мне нужно решение, чтобы предоставить мне версию .СЕТЬ времени выполнения как полной структуры, так и .NET Core.
На машине со следующими версиями .СЕТЬ:
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
Как я могу точно получить версии времени выполнения для разных платформ, зная, что параметр реестра недоступен за пределами Окна.
Под «версией времени выполнения» вы подразумеваете версию CLR, верно?
@HenkHolterman, я считаю, что версия CLR - это то, что возвращает Environment.Version, но он возвращает одну и ту же версию как для ядра, так и для полной структуры. В данном случае мне нужна версия фреймворк. Документы, кажется, еще больше сбивают с толку, ссылка, которую я разместил в своем комментарии выше, относится к получению версии фреймворка, а затем к интерпретации версии на основе возвращенной версии CLR. Но это не говорит о .NET Core.
Вы видите ту же версию CLR в выходных данных Environment.Version, потому что, начиная с .NET Framework 4.6, и Framework, и Core работают в среде CLR, совместимой с .NET Standard 2.0: они действительно одинаковы (что, конечно, не отвечает на ваш реальный вопрос) .





Единого способа сделать это пока нет, хотя есть открытый запрос для этого здесь, который вы можете отслеживать. Если вы нажмете на различные проблемы, которые ссылаются на это обсуждение, и на проблемы, упомянутые ниже, вы увидите, что прямо сейчас есть некоторые ошибки в некоторых реализациях, но есть активная работа (одна из проблем была связана с проверкой только 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. Я сомневаюсь, что когда-нибудь будет хороший способ получить изображение полный всех целей, стоящих за данным набором выполняющихся сборок ...
На самом деле, если подумать, подход рефлексии .NET Core мощь работает с .NET Framework ... Я не подумал попробовать его. Но я думаю, что в долгосрочной перспективе на самом деле планируется третий (унифицированный) метод (который сегодня вообще не работает) - вы можете найти его где-то в перекрестной ссылке из этих ссылок.
Подход рефлексии на полнофункциональной платформе возвращает null для TargetFrameworkAttribute, поэтому его нельзя там использовать.
Я считать, это на самом деле один из отчетов об ошибках, с которыми вы столкнетесь, если будете преследовать все эти перекрестные ссылки github - что, вероятно, означает, что в долгосрочной перспективе отражение будет поддерживать любые другие API, которые они добавляют. В любом случае удачи!
Для .NET Framework подход будет возвращать, какая .NET Framework выполняет «целевое» приложение, а не то, что оно установлено в системе.
(пропустил 5-минутное окно для обновления вышеприведенного комментария) То же самое верно и для .NET Core - он сообщит вам версию среды выполнения, в которой он был нацелен для запуска. Если вы хотите узнать фактическую версию среды выполнения, в которой вы работаете, взгляните на предложенное мной решение.
В последней версии .NET Core 3.0 RC1 сообщается, что свойство System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription будет возвращать правильную версию текущей среды выполнения .NET, в которой выполняется сборка. Также свойство System.Environment.Version также должно работать должным образом.
Если вы хотите узнать, какая версия .NET Framework установлена на компьютере, вам следует использовать задокументированный ключ реестра Release Key. Этот ключ регистрируется в системе при установке .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, когда нам нужно проверить, какая версия установлена на машине).
Для .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);
}
Интересно, но, к сожалению, не работает с автономными приложениями. проголосовали независимо.
Спасибо! Да, для автономных приложений это не сработает. Но для тех, кто знает среду выполнения во время разработки, и это не изменится при развертывании приложения.
значение для 4.7.2 = 461808, поэтому if (value> = 461808) вернет новую версию (4, 7, 2);
@MoonWaxing Изменено в соответствии с вашим предложением
Что вы имеете в виду, говоря «получить исполняемые версии для разных платформ»? Ваш код точно дает вам версии .NET, а
RuntimeInformation.OSDescriptionпредоставит вам ОС. Что вы имеете в виду под "параметром реестра"? Вы хотите посмотреть реестр, если вы работаете в Windows?