从.Net程序集中检索目标框架版本和目标框架配置文件

时间:2011-07-28 05:59:56

标签: .net reflection .net-assembly target-framework

在编译.Net程序集时,有什么方法可以访问用于TargetFrameworkVersion和/或TargetFrameworkProfile的值?

我正在谈论的值是包含项目文件的值

<?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>

基本上,我想知道编译程序集时框架的目标版本是什么,如果可能的话,也可以找到目标框架配置文件。

我不是在谈论当前加载的CLR版本,Environment.Version不是我想要的。

理想情况下,解决方案将使用System.Reflection,但如果我不得不求助于其他方法。

6 个答案:

答案 0 :(得分:12)

如果您对编译程序集的 CLR 版本感到满意,则可以使用Assembly.ImageRuntimeVersion属性。根据MSDN,该属性:

  

表示保存在包含清单的文件中的公共语言运行库(CLR)的版本。

  

默认情况下,ImageRuntimeVersion设置为用于构建程序集的CLR的版本。但是,它可能在编译时设置为另一个值。

当然,这并没有为您提供.NET Framework的特定版本(例如:.NET Framework 2,3.0和3.5都在2.0 CLR上)。

如果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开头的程序集,以避免与其他库的误报。如果您看到引用的任何System。*程序集的版本为3.5.x.x,那么您也可以非常确定它是为3.5版本构建的。


正如您所注意到的,我不相信TargetFrameworkProfile会逃过Visual Studio。但是,如果恰好有应用程序的app.config文件,Visual Studio可能已将目标框架放在那里。例如,如果将项目设置为使用4.0 Client Profile,Visual Studio将创建一个app.config,如下所示:

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

答案 1 :(得分:4)

如果使用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();
    }
}

答案 2 :(得分:0)

还尝试使用此示例在运行时检索.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)

答案 3 :(得分:0)

njappboy的解决方案效果很好。我需要VB.Net版本,所以这是转换。

Dim assems = AppDomain.CurrentDomain.GetAssemblies()
Dim filteredType = GetType(Runtime.Versioning.TargetFrameworkAttribute)
Dim assemblyMatches = assems.[Select](Function(x) New With {Key .Assembly = x,
            Key .TargetAttribute = CType(x.GetCustomAttribute(filteredType),
            Runtime.Versioning.TargetFrameworkAttribute)}).Where(
            Function(x) x.TargetAttribute IsNot Nothing)
For Each assem In assemblyMatches
    Dim framework = New System.Runtime.Versioning.FrameworkName(
        assem.TargetAttribute.FrameworkName)

    Console.WriteLine("Assembly: '{0}' targets .NET version: '{1}'.",
                      assem.Assembly.FullName, framework.Version)
Next

答案 4 :(得分:0)

{{1}}

答案 5 :(得分:0)

这应该有效!

->编译bin \ net45 \ myapp.exe =“ .NET Framework 4.5”

var asm = Assembly.GetExecutingAssembly();
var b = asm.CustomAttributes.FirstOrDefault(a => a.AttributeType == typeof(TargetFrameworkAttribute));
var strFramework = b.NamedArguments[0].TypedValue.Value;

Console.WriteLine(strFramework);