【问题标题】:Future-proofing the .NET version detection面向未来的 .NET 版本检测
【发布时间】:2011-06-01 07:00:51
【问题描述】:

不要击败deadhorse,但是,我正在寻找一种方法来检测已安装的 .NET 框架。似乎提供的解决方案(在链接中)都很好,直到发布了新版本的框架,然后所有的赌注都结束了。原因是检测依赖于注册表项,而且框架的 v4 似乎违反了惯例,现在必须采取额外的步骤来检测 v4。

有没有办法检测 .NET 框架,当 .NET v5 出现时也可以工作。

编辑:好的,对于未来几代沮丧的 .NET 版本寻求者,这里是实现它的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
using Microsoft.Win32;

private List<string> GetInstalledDotNetFrameworks()
{
    string key = string.Empty;
    string version = string.Empty;
    List<string> frameworks = new List<string>();

    var matches = Registry.LocalMachine
                .OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP")
                .GetSubKeyNames().Where(keyname => Regex.IsMatch(keyname, @"^v\d"));


    // special handling for v4.0 (deprecated) and v4 (has subkeys with info)
    foreach (var item in matches)
    {
        switch (item)
        {
            case "v4.0":  // deprecated - ignore
                break;

            case "v4":// get more info from subkeys

                key = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\" + item;
                string[] subkeys = Registry.LocalMachine
                    .OpenSubKey(key)
                    .GetSubKeyNames();


                foreach (var subkey in subkeys)
                {
                    key = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\" + item + @"\" + subkey;
                    version = Registry.LocalMachine
                            .OpenSubKey(key)
                            .GetValue("Version").ToString();

                    version = string.Format("{0} ({1})", version, subkey);
                    frameworks.Add(version);
                }


                break;
            case "v1.1.4322":   // special case, as the framework does not follow convention
                frameworks.Add(item);
                break;
            default:

                try
                {
                    // get the Version value
                    key = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\" + item;
                    version = Registry.LocalMachine
                            .OpenSubKey(key)
                            .GetValue("Version").ToString();

                    frameworks.Add(version);

                }
                catch
                {
                    // most likely new .NET Framework got introduced and broke the convention
                }

                break;

        }

    }

    // sort the list, just in case the registry was not sorted
    frameworks.Sort();

    return frameworks;
}

【问题讨论】:

    标签: c# .net detection


    【解决方案1】:

    您希望我们能告诉您未来吗? :) 你为什么首先需要它?我的意思是,如果您为 v4 编写应用程序,安装与不安装 v5 有什么区别?您可以在 app.config 中指定您支持的版本,但您无法提前知道下一个版本将是什么,或者即使您的应用程序将在该版本上运行。每当出现新框架时,您都必须测试您的应用程序,并决定是否要迁移。如果您迁移,那么您对 ​​app.config 和可能的代码进行更改,并发布一个新版本。如果您不这样做,那么您仍然需要安装较旧的框架版本。不像 v5 出来,人们会开始卸载所有以前的框架。我的机器上还有 v1.1 和 v2,我想它们会保留一段时间。

    【讨论】:

    • 这不是重点——我的应用程序不使用数据。然而,因为我的应用程序被我的组织中的大量人员使用,决定使用我的应用程序作为收集用户机器能力信息的一种方式(例如 cpu、ram、hd 空间等)的权力。 ..),包括 .NET 框架。由于检测机制发生了变化,我似乎必须每隔一两年重写一次这个例程。我想把它放在过去,并有一些可行的方法。
    【解决方案2】:

    我同意 fejesjoco 的观点。为什么您甚至想要检测您的代码尚未编译的未来版本?

    如果您查看 Framework 文件夹 (C:\Windows\Microsoft.NET\Framework),您会看到所有先前版本的 Framework 都与最新版本一起安装。如果你的代码是针对 4.0 编译的,并且 5.0 出来了,它仍然会有一个 4.0 的文件夹。

    如果您能给我们提供更多关于您为什么要检测未来版本的背景信息,我们或许可以为您提供更好的帮助。

    【讨论】:

    • 查看我评论中的上下文以获取@fejesjoco 的答案。
    • 好吧,这更有意义。为什么不循环访问相关 .Net 文件夹下的注册表项来获取已安装的框架版本? HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework[v2.0|v3.0|v4.0.30319]。我猜下一个版本的框架会得到 v4.5 或者 v5.0 应该很简单,你觉得呢?
    【解决方案3】:

    在检测工具中包含自动更新功能?

    【讨论】:

      【解决方案4】:

      简而言之,您可以大致使用这个(更完整的解决方案见下文):

      Microsoft.Win32.Registry.LocalMachine
          .OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP")
          .GetSubKeyNames().Where(keyname=>Regex.IsMatch(keyname,@"^v\d"))
      

      在我的机器上,返回:v2.0.50727、v3.0、v3.5、v4、v4.0。子项可用于检测服务包(可能相关)。此外,使用密钥 SOFTWARE\Microsoft\.NETFramework 返回 v2.0.50727、v3.0 和 v4.0.30319 - 嗯,可爱,略有不同!

      不能保证这种模式会成立,但这是一个非常合理的选择 :-)。 http://support.microsoft.com/kb/318785 有一些关于描述版本控制的注册表详细信息的更多信息,特别是,您可能需要检查 Install - 但正如 v4.0 所示,这很棘手。

      编辑:我已对此进行了扩展,以检测包含安装信息的注册表的任意子键,以便正确检测 v4 客户端和完整配置文件。另外,RegistryKey 类型是IDisposable,看起来 Dispose 方法确实在做某事(注册表项解锁)。

      var versionList = new List<string>();
      using(var ndpKey=Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP")) {
          Action<RegistryKey, Action<RegistryKey,string>> processKids = (node, action) => {
              foreach(var childname in node.GetSubKeyNames())
                  using(var child = node.OpenSubKey(childname))
                      action(child,childname);
          };
      
          Action<RegistryKey, Func<RegistryKey, bool>> visitDescendants = null;
          visitDescendants = (regkey, isDone) => {
              if(!isDone(regkey))
                  processKids(regkey, (subkey, subkeyname)=>visitDescendants(subkey,isDone));
          };
      
          processKids(ndpKey, (versionKey, versionKeyName) => {
              if(Regex.IsMatch(versionKeyName,@"^v\d")) {
                  visitDescendants(versionKey, key => {
                      bool isInstallationNode = Equals(key.GetValue("Install"), 1) && key.GetValue("Version") != null;
                      if(isInstallationNode)
                          versionList.Add(
                              key.Name.Substring(ndpKey.Name.Length+1) 
                              + (key.GetValue("SP")!=null ? ", service pack "+ key.GetValue("SP"):"")
                              + " ("+key.GetValue("Version")  +") "
                          );
                      return isInstallationNode;
                  });
              }
          });
      }
      

      versionList 然后包含:

      v2.0.50727, service pack 2 (2.0.50727.4927)   
      v3.0, service pack 2 (3.0.30729.4926)   
      v3.5, service pack 1 (3.5.30729.4926)   
      v4\Client (4.0.30319)   
      v4\Full (4.0.30319)   
      

      【讨论】:

      • 谢谢,我不知道这个注册表项 - 以为我必须转到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP。我认为这可能会奏效。
      • 抱歉,这实际上不起作用。 Software/Microsoft/.NETFramework 未列出 v3.5
      • 已修复 - 我现在正在使用 NDP 注册表项。
      • 是的,v4.0 密钥涉及一些技巧 - 需要应对客户端和完整安装。此外,不推荐使用 v4 密钥。
      • 顺便说一句,v1.1 失败,因为它没有弹出版本值。我更新了问题中的代码。
      猜你喜欢
      • 2011-02-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      • 2016-03-17
      • 2018-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多