面向未来的.NET版本检测

时间:2010-12-29 22:06:36

标签: c# .net detection

不要超越dead horse,但是,我正在寻找一种方法来检测已安装的.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;
}

4 个答案:

答案 0 :(得分: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)   

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

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

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

答案 3 :(得分:0)

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