Обнаружение и использование Windows QFE / patch для установки - PullRequest
15 голосов
/ 28 февраля 2012

Наш установщик WiX развертывает приложение .NET 4.0 WinForms на Windows Vista и 7 рабочих столах. Приложение включает в себя Portable Class Library , для которой требуется .NET patch (KB2468871). Нам необходимо установить патч в качестве предварительного условия. Существует несколько способов применения патча:

  1. Загрузите исправление KB2468871 и установите его
  2. Установка Портативных библиотечных инструментов
  3. В качестве обязательного условия использования ClickOnce (может быть вариацией # 1)

Используя совет из аналогичного вопроса , я создал CustomAction для проверки QFE (# 1), которое, как я продемонстрировал, возвращает true при обнаружении.

private static bool IsPatchAlreadyInstalled()
{
    // If the patch is installed, we can find it using WMI
    var query = new SelectQuery("SELECT HotFixID FROM Win32_QuickFixEngineering WHERE HotFixID = 'Q2468871' OR HotFixID = 'KB2468871'");
    var results = new ManagementObjectSearcher(query).Get();
    return results.Count > 0;
}

К сожалению, это не работает на моем компьютере разработчика, так как патч был установлен как часть Инструментов (# 2). Я еще не был свидетелем ситуации № 3.

Как лучше определить, был ли установлен патч?

Ответы [ 3 ]

13 голосов
/ 01 марта 2012

Win32_QuickFixEngineering не вернет все обновления.Фактически, он возвращает только обновления, ограниченные QFE:

Обновления, предоставляемые установщиком Microsoft Windows (MSI) или сайтом обновлений Windows (http://update.microsoft.com), не возвращаются Win32_QuickFixEngineering.

Обновление, которое вы ищете, является патчем MSI. Используйте Microsoft.Deployment.WindowsInstaller (он же DTF - Фонд средств развертывания , часть Набор инструментов WiX ) для запроса примененных исправлений MSI:

public static bool IsPatchAlreadyInstalled(string productCode, string patchCode)
{
    var patches = 
        PatchInstallation.GetPatches(null, productCode, null, UserContexts.Machine, PatchStates.Applied);

    return patches.Any(patch => patch.DisplayName == patchCode);
}

В этом случае KB2468871 является одним из обновлений .NET Framework 4. Следующее вернет true, если обновления имеютбыли применены на машине:

IsPatchAlreadyInstalled("{F5B09CFD-F0B2-36AF-8DF4-1DF6B63FC7B4}", "KB2468871");// .NET Framework 4 Client Profile 64-bit
IsPatchAlreadyInstalled("{8E34682C-8118-31F1-BC4C-98CD9675E1C2}", "KB2468871");// .NET Framework 4 Extended 64-bit
IsPatchAlreadyInstalled("{3C3901C5-3455-3E0A-A214-0B093A5070A6}", "KB2468871");// .NET Framework 4 Client Profile 32-bit
IsPatchAlreadyInstalled("{0A0CADCF-78DA-33C4-A350-CD51849B9702}", "KB2468871");// .NET Framework 4 Extended 32-bit
11 голосов
/ 29 апреля 2015

Я добился этого с помощью WiX Burn, используя следующий фрагмент (используя коды продуктов от @KMoraz):

<!-- KB2468871 update to support portable class libraries (PCL) on XP -->
<Fragment>
  <!-- codes from http://stackoverflow.com/a/9506530 -->
  <util:ProductSearch ProductCode="{0A0CADCF-78DA-33C4-A350-CD51849B9702}" 
                      Variable="KB2468871_NET32_Installed" />
  <util:ProductSearch ProductCode="{8E34682C-8118-31F1-BC4C-98CD9675E1C2}" 
                      Variable="KB2468871_NET64_Installed" />

  <PackageGroup Id="NDP40_KB2468871_v2">
    <ExePackage Id="NDP40_KB2468871_v2_x86" Compressed="no" Vital="yes" Permanent="yes"
                SourceFile="NDP40-KB2468871-v2-x86.exe"
                DownloadUrl="http://download.microsoft.com/download/2/B/F/2BF4D7D1-E781-4EE0-9E4F-FDD44A2F8934/NDP40-KB2468871-v2-x86.exe"
                DetectCondition="KB2468871_NET32_Installed"
                InstallCondition="NOT VersionNT64"
                InstallCommand="/q"/>

    <ExePackage Id="NDP40_KB2468871_v2_x64" Compressed="no" Vital="yes" Permanent="yes"
                SourceFile="NDP40-KB2468871-v2-x86.exe"
                DownloadUrl="http://download.microsoft.com/download/2/B/F/2BF4D7D1-E781-4EE0-9E4F-FDD44A2F8934/NDP40-KB2468871-v2-x64.exe"
                DetectCondition="KB2468871_NET64_Installed"
                InstallCondition="VersionNT64"
                InstallCommand="/q"/>
  </PackageGroup>
</Fragment>

Пространство имен util относится к Wix Util Extension .Вам понадобится xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" в вашем корневом элементе и ссылка на WixUtilExtension.dll.

Установщики будут автоматически загружены при необходимости.Вам нужно, чтобы файлы инсталлятора сохранялись локально в корне вашего проекта WiX с тем же именем, которое указано SourceFile для его сборки, но они не будут добавлены в комплект установки, поскольку для Compressed установлено значение no.

10 голосов
/ 06 марта 2012

Я играл с подобной ситуацией и нашел ответ @KMoraz почти правильным.(ПРИМЕЧАНИЕ: @KMoraz, я бы оставил это как комментарий, но у меня пока нет представителя!)

Пространство имен Microsoft.Deployment.WindowsInstaller кажется подходящим, но фильтрация по коду продукта может бытьслишком ограничительныйЯ столкнулся с проблемой, когда патч был установлен на машине, но не связан ни с кодом продукта {F5B09CFD-F0B2-36AF-8DF4-1DF6B63FC7B4}, ни с {8E34682C-8118-31F1-BC4C-98CD9675E1C2}.

Мое решение заключалось в том, чтобы вместо этого использовать PatchInstallation.AllPatches, который возвращает нефильтрованный список установленных исправлений в системе, а затем искать ответ с помощью linq.

public static bool CheckForPatch()
{
    return IsPatchAlreadyInstalled("KB2468871")
}

public static bool IsPatchAlreadyInstalled(string patchCode)
{
    var patches = PatchInstallation.AllPatches.ToList();
    patches.ForEach(x => Console.WriteLine("--found patch {0} for {1}",x.DisplayName,x.ProductCode));
    return patches.Any(patch => patch.DisplayName == patchCode);
}

Пример вывода:

--found patch Microsoft Office 2010 Service Pack 1 (SP1) for {90140000-001F-0409-0000-0000000FF1CE}
--found patch Update for Microsoft Office 2010 (KB2553270) 32-Bit Edition for {90140000-001F-0409-0000-0000000FF1CE}
--found patch Microsoft Office 2010 Service Pack 1 (SP1) for {90140000-001F-0C0A-0000-0000000FF1CE}
--found patch Update for Microsoft Office 2010 (KB2553270) 32-Bit Edition for {90140000-001F-0C0A-0000-0000000FF1CE}
--found patch Microsoft Office 2010 Service Pack 1 (SP1) for {90140000-001F-040C-0000-0000000FF1CE}
--found patch Update for Microsoft Office 2010 (KB2553270) 32-Bit Edition for {90140000-001F-040C-0000-0000000FF1CE}
--found patch KB2533523 for {3C3901C5-3455-3E0A-A214-0B093A5070A6}
--found patch KB2518870 for {3C3901C5-3455-3E0A-A214-0B093A5070A6}
--found patch KB2656351 for {3C3901C5-3455-3E0A-A214-0B093A5070A6}
--found patch KB2633870 for {3C3901C5-3455-3E0A-A214-0B093A5070A6}
--found patch KB2468871 for {3C3901C5-3455-3E0A-A214-0B093A5070A6}
--found patch KB2572078 for {3C3901C5-3455-3E0A-A214-0B093A5070A6}
--found patch KB2533523 for {0A0CADCF-78DA-33C4-A350-CD51849B9702}
--found patch KB2656351 for {0A0CADCF-78DA-33C4-A350-CD51849B9702}
--found patch KB2468871 for {0A0CADCF-78DA-33C4-A350-CD51849B9702}
--found patch KB2487367 for {0A0CADCF-78DA-33C4-A350-CD51849B9702}
...