System.Environment.Version提供不准确的值

时间:2013-04-22 00:20:29

标签: c# .net

我有一个简单的问题:当我在Visual Studio 2012中转到HELP->关于时,窗口指示我使用的.NET版本是4.5.50709。但是,当我执行以下代码时:

Console.WriteLine(Environment.Version);

我得到版本4.0.30319.18034。是什么赋予了?在Troelsen的 Pro C#5& .NET 4.5 Framework ,第81页,它指出Version属性返回一个表示.NET平台版本的对象。这是不正确的?上一个问题的线程表明此属性返回CLR版本。如果是这种情况,那么Version对象的目的是什么(例如,知道CLR版本而不是框架版本的用途是什么),以及如何实际获得框架版本本身?

2 个答案:

答案 0 :(得分:17)

CLR(公共语言运行时)版本是4.0.30319.18034。它从4.0.30319开始,因为.NET 4.5是.NET 4.0程序集的就地升级。

  

4.5更新完全取代了.NET 4.0运行时,并将实际版本号设置为v4.0.30319。

     

source 1source 2

但是您的版本号可能代表.NET 4.5并带有一些更新,可能由用户Daniel从this list推断出来:

  

以下是我见过的运行时版本的一些示例:

     
      
  • 4.0.30319.1 = .NET 4.0 RTM
  •   
  • 4.0.30319.269 =我们在用户收集的数据中看到的最常见的.NET 4.0版本
  •   
  • 4.0.30319.544 =我们用户的一小部分安装的另一个.NET 4.0版本
  •   
  • 4.0.30319.17626 = .NET 4.5 RC
  •   
  • 4.0.30319.17929 = .NET 4.5 RTM
  •   
  • 4.0.30319.18010 =我的Windows 8计算机上的当前版本
  •   

主要版本,次版本和版本号都没有改变,所以我认为他们认为.NET 4.0和4.5之间的区别对大多数人来说都不重要。期望某些版本4.0.30319的.NET 4.0应用程序仍然可以在.NET 4.5下按预期工作。


无论您是编写.NET 4.0还是4.5,您都要编译完全相同的.NET程序集。唯一的区别是.NET 4.5中的一些新类在编译.NET 4.0时是隐藏(好像它们从未存在过)。因此,告诉.NET 4.0和4.5之间区别的唯一可靠方法似乎是Christian.K in his post提出的相当黑客的方法,它不涉及版本号:

  

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

答案 1 :(得分:2)

就像练习一样,我想知道Visual Studio如何检索.NET版本。您可以查询注册表以查看安装了哪些版本,我想出了这段代码:

static void Main(string[] args)
{
    Console.WriteLine("The following .NET versions are installed:");
    var vers = SearchRegistry(Registry.LocalMachine, "Software\\Microsoft\\NET Framework Setup\\NDP", "Version")
        .GroupBy(v => v)
        .Select(v => (string)v.Key)
        .OrderBy(s => s);

    foreach (string s in vers)
        Console.WriteLine(s);

    Console.WriteLine(string.Format("Newest Installed .NET version: {0}", vers.Last()));
}

private static IEnumerable<object> SearchRegistry(RegistryKey root, string subkey, string search)
{
    foreach (string sub in root.OpenSubKey(subkey).GetSubKeyNames())
    {
        foreach (string val in root.OpenSubKey(subkey).OpenSubKey(sub).GetValueNames())
            if (val == search)
                yield return root.OpenSubKey(subkey).OpenSubKey(sub).GetValue(val);

        foreach (var o in SearchRegistry(root.OpenSubKey(subkey), sub, search))
            yield return o;
    }
}