Извлечь версию целевой платформы и профиль целевой структуры из сборки .Net

Есть ли способ получить доступ к значениям, которые были использованы для TargetFrameworkVersion и/или TargetFrameworkProfile, когда была собрана сборка .Net?

Значения, о которых я говорю, содержат файлы проекта

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OtherStuff>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <OtherStuff>
  </PropertyGroup>
  <OtherStuff>
  </OtherStuff>
</Project>

В основном я хотел бы узнать, какая была целевая версия Framework, когда сборка была скомпилирована и, по возможности, профиль целевой структуры.

И я не говорю о загружаемой в настоящее время версии CLR, Environment.Version не то, что мне нужно.

В идеале решение будет использовать System.Reflection, но если мне придется прибегать к другим методам, я буду.

Ответы

Ответ 1

Если вы будете довольны версией CLR, скомпилированной сборкой, вы можете использовать свойство Assembly.ImageRuntimeVersion. Согласно MSDN, это свойство:

представляющий версию среды выполнения общего языка (CLR), сохраненную в файле, содержащем манифест.

и

По умолчанию ImageRuntimeVersion устанавливается на версию CLR, используемую для сборки сборки. Однако во время компиляции оно могло быть установлено на другое значение.

Конечно, это не дает вам определенную версию .NET Framework (например:.NET Frameworks 2, 3.0 и 3.5 все находятся на CLR 2.0).

Если версия CLR недостаточна, вы можете попробовать "оценить" (угадать разумно), какую версию она должна быть основана на собраниях, которые она ссылается. Для .NET 1 и 4 версии CLR должно быть достаточно. Однако, если версия CLR была 2.0, вы бы не знали, означает ли это 2.0, 3.0 или 3.5, чтобы вы могли попробовать еще одну логику. Например, если вы заметили, что Ассамблея ссылается на System.Core (используя Assembly.GetReferencedAssemblies()), вы должны знать, что версия 3.5, поскольку System.Core была новой в 3.5, Это не совсем твердо, потому что данная сборка не может использовать какие-либо типы из Собрания, чтобы вы не смогли ее поймать. Чтобы попытаться уловить больше случаев, вы можете прокрутить все ссылочные сборки и проверить их номера версий - возможно, фильтровать только сборки, которые начинаются с System, чтобы избежать ложных срабатываний с другими библиотеками. Если вы видите какие-либо системные сборки. *, На которые ссылается версия 3.5.x.x, вы также можете быть уверены, что она была создана для 3.5.


Как вы заметили, я не верю, что TargetFrameworkProfile ускользает от Visual Studio. Тем не менее, если для приложения есть файл app.config, Visual Studio, возможно, разместила целевую инфраструктуру. Например, если вы настроили проект на использование профиля клиента 4.0, Visual Studio создаст app.config следующим образом:

<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
  </startup>
</configuration>

Ответ 2

Если сборка была скомпилирована с помощью TargetFrameworkAttribute (с учетом области сборки), вы можете легко и равномерно определить цель профиля каркаса.

Попробуйте этот пример и укажите свои собственные сборки с разными целями.

class Program
{
    static void Main(string[] args)
    {


        // Lets examine all assemblies loaded into the current application domain.
        var assems = AppDomain.CurrentDomain.GetAssemblies();

        // The target framework attribute used when the assemby was compiled.
        var filteredType = typeof(TargetFrameworkAttribute);

        // Get all assemblies that have the TargetFrameworkAttribute applied.
        var assemblyMatches = assems.Select(x => new { Assembly = x, TargetAttribute = (TargetFrameworkAttribute)x.GetCustomAttribute(filteredType) })
                                    .Where(x => x.TargetAttribute != null);

        // Report assemblies framework target
        foreach (var assem in assemblyMatches)
        {
            var framework = new System.Runtime.Versioning.FrameworkName(assem.TargetAttribute.FrameworkName);
            Console.WriteLine("Assembly: '{0}' targets .NET version: '{1}'.",
                                assem.Assembly.FullName,
                                framework.Version);
        }

        Console.ReadLine();
    }
}

Ответ 3

Попробуйте также этот пример, чтобы получить как целевые, так и текущие версии платформы .NET во время выполнения (работает для .NET V4.X):

    Dim ca As Object() = System.Reflection.Assembly.GetEntryAssembly().GetCustomAttributes(False)

    For Each c In ca.Where(Function(x) x.TypeId.Name = "TargetFrameworkAttribute")
        Console.WriteLine("Target .NET framework for " & Application.ProductName & " : " & c.FrameworkDisplayName)
    Next

    Console.WriteLine("Current .NET framework for " & Application.ProductName & " : " & System.Diagnostics.FileVersionInfo.GetVersionInfo(GetType(Integer).Assembly.Location).ProductVersion)