如何在运行时检测.NET版本4.5当前正在运行您的代码?

Eve*_*req 60 .net clr version .net-4.5

我从http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27541安装了.NET 4.5 Developer预览版,它取代了.NET 4.0版本.

但是,检测.NET框架版本的旧方法似乎返回4.0(更准确地说是我的PC上的4.0.30319.17020),而不是4.5(确定可能是为了向后兼容,或者?):

using System;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var version = Environment.Version;
            Console.WriteLine(version.ToString());
            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何检测我的代码是否真的由.NET 4.5执行?

Chr*_*n.K 106

您需要明确区分CLR(即"运行时")和框架库(即"框架").您在第一个或第一个上执行代码,您的代码将被编译并使用后者.不幸的是,当使用术语".NET 版本 "时,通常指的是运行时和框架的整个包,无论它们各自的版本如何 - 如前所述 - 都可以不同.

您可以检测已安装的框架版本.但是,这并不能告诉您在运行时实际使用的是哪一个.

我不确定4.5,但2.0和3.0或3.5 Environment.Version没有帮助,因为它总是返回2.0,因为所有这些框架版本都使用CLR 2.0.我假设使用框架 4.5,CLR版本仍然是4.0,这可以解释Environment.Version即使在这种情况下返回4.0.x.

可能对您有用的技术是检查核心库(mscorlib,System.Core等)中的类型,方法或属性,您只知道它们存在于特定的.NET框架版本之后.

例如,ReflectionContext类在.NET framework 4.5中似乎是全新的,并且可以方便地存在mscorlib.所以你可以这样做.

  public static bool IsNet45OrNewer()
  {
      // Class "ReflectionContext" exists from .NET 4.5 onwards.
      return Type.GetType("System.Reflection.ReflectionContext", false) != null;
  }
Run Code Online (Sandbox Code Playgroud)

说了这么多,人们可以质疑为什么你需要知道你正在使用哪个.NET版本.只需尝试访问您需要的功能,如果不存在,可能会优雅地回退到其他东西(旧版本中可用).

更新:请注意,术语.NET 4.5指的是构成基类库(BCL)和更多(统称为"框架")的几个程序集的整个包以及运行时本身,即CLR - 两者都可以具有如前所述,不同的版本.

我不为微软工作,也没有深入了解缺乏(单一)函数或API来获得".NET框架版本"背后的真正原因,但我可以做出有根据的猜测.

  1. 目前尚不清楚特定功能/ API应提供哪些信息.甚至BCL的各个程序集也不共享公共(程序集/文件)版本.例如,对于.NET 3.0和3.5,mscorlib.dll具有版本2.0.x,而只有WCF和WF的新程序集具有3.0.我认为即使使用.NET 3.5,System.ServiceModel.dll仍然有版本3.0.x. 我想说的是,框架的所有程序集都没有统一的版本.那么API应该调用什么,比方说,System.Environment.FrameworkVersion返回?该版本的价值是多少(即使它确实返回了像4.5这样的"符号"版本,它也没什么价值,不是吗?).

  2. 太具体某些新功能可能会在SP中到达现有版本,还会成为新版本的一部分.进行功能检查时,您的应用程序可能在以前的版本上运行得很好,已经更新,而在显式版本检查时,它可能不必要地将自己限制在最新版本.我没有.NET世界的例子,但总的来说(在Windows本身,例如WMI)它可以而且确实发生了.

  3. 不想要.我可以想象,一个方法来计算应用程序当前正在使用的"框架的版本",它们甚至不希望它们提供.在本机/ Win32世界中,版本检查谬误的历史很长而且非常糟糕(请参阅"不要检查版本"段落以了解适用于.NET的概念).例如,人们使用GetVersionGetVersionEx错误的API,只是检查他们运行他们认为是编写应用程序时最新的版本.所以,当应用程序是在Windows的新版本上运行,它不会跑,即使功能他们真的是使用仍然存在.微软可能已经考虑过这样的问题,因此甚至没有在.NET中提供一些API.

顺便提一下,这是Microsoft 在GetVersion函数的备注部分中建议的内容:

识别当前操作系统通常不是确定特定操作系统功能是否存在的最佳方法.这是因为操作系统可能在可再发行的DLL中添加了新功能.而不是使用GetVersionEx来确定操作系统平台或版本号,而是测试功能本身的存在.

Windows团队博客也有话要说.

我知道所有这些都是关于Windows和本机编程的,但.NET应用程序框架和CLR的概念和危险是相同的.

我认为使用(优雅)回退进行功能检查是一种更可靠,更健壮的方法,可确保您的应用程序向下兼容.如果您只希望您的应用程序使用特定版本的.NET或更新版本,请不要执行任何特殊操作,并依靠.NET本身的向后兼容性.

  • **UPDATE .NET 4.5.1**:如果您需要检查最新的.NET Framework 4.5.1版,请随意使用该版本中引入的其他类型(枚举):**System.Runtime.GCLargeObjectHeapCompactionMode**,例如:`Type.GetType("System.Runtime.GCLargeObjectHeapCompactionMode",false)!= null` (5认同)
  • 我建议大家也阅读Scott Hanselman撰写的以下博客文章:http://www.hanselman.com/blog/NETVersioningAndMultiTargetingNET45IsAnInplaceUpgradeToNET40.aspx.特别是我喜欢将<supportedRuntime version ="v4.0"sku =".NETFramework,Version = v4.5"/>添加到几乎任何应用类型的app.config中,如果您的应用需要.NET,请使用EXCEPT ASP.NET 4.5运行时.(如果用户不可用,将提升用户安装.NET 4.5).然而,它并不完全是检测:( ...无论如何,我要求ASP.NET团队提供+1,如果他们也可以添加对此类配置参数的支持. (4认同)

Jam*_*s L 29

要确定您的应用程序正在运行哪个.NET补丁,请进行此调用以查找mscorlib的内部版本号:

System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion
Run Code Online (Sandbox Code Playgroud)

它目前为我返回4.6.1055.0,对应于.NET 4.6.1.

  • 这次真是万分感谢.鉴于缺乏任何其他可靠的查找运行时的方法,您的答案被低估了.鉴于最近框架版本的质量下降,在尝试诊断模糊的客户端漏洞时,这一点变得越来越重要. (2认同)

Gov*_*ert 25

.NET Framework 4.5是4.0的就地升级.这松散意味着如果您运行的是4.0或4.5版运行时,并且安装了4.5,那么您肯定在4.5上运行.您的支票可能如下.

让我们调用4.0和4.5运行时4.0版本的运行时.

  1. 检查您是否在4.0版本的运行时上运行:

    • 如果您的程序集编译为目标.NET 4.0,或
    • Environment.Version.Major == 4 && Environment.Version.Minor == 0

    然后你运行4.0版本的运行时.

  2. 通过检查已安装的版本,检查4.0版本的运行时是否实际是4.0或4.5版:

    • 在键下HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client,检查_Version_值.如果它始于"4.0"您在4.0运行时运行,如果它以"4.5"您运行4.5运行时开始.


Gle*_*den 7

James提供了在运行时获取mscorlib.dll的"产品版本" 的绝佳答案:

(using System.Diagnostics;)

FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion
Run Code Online (Sandbox Code Playgroud)

这很好用,但是你可以通过检查System.dll来获得更细粒度的结果:

FileVersionInfo.GetVersionInfo(typeof(Uri).Assembly.Location).ProductVersion
Run Code Online (Sandbox Code Playgroud)

请注意,稍有不同的是使用组件typeof(Uri)而不是typeof(int),因为前者是定义System.dll而不是mscorlib.dll后者.对于一个针对.NET 4.7.1的简单C#控制台程序,我的系统当前报告的差异如下:

...\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll 4.7.2600 .0 ...\Microsoft.NET\Framework\v4.0.30319\System.dll 4.7.2556 .0

至于区分是否有用或如何使用更详细的信息,这将取决于具体情况.


Vip*_*pul 5

您可以通过在注册表中检查名为的值的子项来测试是否安装了.NET Framework 4.5.NET Framework 4.这种情况的存在表明.NET Framework 4.5已经安装在该计算机上.值是版本号.要确定是否已安装.NET Framework 4.5的最终发行版,请检查是否等于或大于.HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\FullDWORDReleaseDWORDRelease378389

  • 注册表项和Christian.K的IsNet45OrNewer()函数是完美的.谢谢,@ Vipul! (2认同)
  • 从MSDN有关此注册表值:http://msdn.microsoft.com/en-us/library/hh925568.aspx'''您必须具有管理凭据才能运行此示例''' (2认同)