Защита от обнаружения версии .NET в будущем - PullRequest
3 голосов
/ 30 декабря 2010

Не для того, чтобы победить мертвых лошадей , однако, я ищу способ обнаружить установленные платформы .NET. Кажется, что все предоставленные решения (в ссылках) хороши до тех пор, пока не выйдет новая версия фреймворка, а затем все ставки не будут приняты. Причина этого заключается в том, что обнаружение основывается на разделах реестра, и кажется, что версия 4 платформы нарушила соглашение, и теперь необходимо предпринять дополнительные шаги для обнаружения версии 4.

Есть ли способ обнаружения .NET Framework, который также будет работать при появлении .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 ]

4 голосов
/ 30 декабря 2010

Короче говоря, вы можете использовать это примерно (см. Ниже для более полного решения):

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)   
3 голосов
/ 30 декабря 2010

Я согласен с fejesjoco. Почему вы даже хотите обнаружить будущую версию, против которой ваш код не был скомпилирован?

Если вы загляните в папку Framework (C: \ Windows \ Microsoft.NET \ Framework), вы увидите, что все предыдущие версии Framework установлены вместе с самой последней версией. Если ваш код скомпилирован под 4.0 и выйдет 5.0, у него все равно будет папка для 4.0.

Если бы вы могли дать нам немного больше информации о том, почему вы хотите обнаруживать будущие версии, мы можем помочь вам лучше.

3 голосов
/ 30 декабря 2010

Ожидаете ли вы, что мы можем сказать вам будущее? :) Зачем тебе это в первую очередь? Я имею в виду, если вы пишете приложение для v4, какая разница, установлена ​​версия v5 или нет? Вы можете указать в app.config, какие версии вы поддерживаете, но вы не можете заранее знать, какой будет следующая версия, или даже если ваше приложение будет работать на этом. Всякий раз, когда выходит новый фреймворк, вам нужно протестировать свое приложение и решить, хотите ли вы мигрировать или нет. Если вы мигрируете, вы вносите изменения в app.config и, возможно, код, а также выпускаете новую версию. Если вы этого не сделаете, вам все равно потребуется установить более старую версию фреймворка. Это не так, как v5 выходит, и люди начнут удалять все предыдущие фреймворки. У меня все еще есть v1.1 и v2 на моей машине, и я думаю, что они останутся на некоторое время.

0 голосов
/ 30 декабря 2010

Включить функцию автообновления в инструменте обнаружения?

...