2012-02-28 7 views
15

Nasz instalator WiX wdraża aplikację WinForms .NET 4.0 na Windows Vista i 7 komputerów stacjonarnych. Aplikacja zawiera Portable Class Library, która wymaga .NET patch (KB2468871). Musimy zainstalować poprawkę jako warunek wstępny. Istnieją różne sposoby, że łatka może być zastosowane:Wykryj i wymagaj Windows QFE/patch podczas instalacji

  1. pobrać poprawkę KB2468871 i zainstalować go
  2. Zainstalować Portable Library Tools
  3. Jako warunek przy użyciu ClickOnce (może być odmianą # 1)

Korzystając z porady od a similar question, stworzyłem CustomAction, aby sprawdzić, czy QFE (nr 1), który pokazałem, zwraca wartość true, gdy zostanie znaleziony.

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

Niestety, to nie powiedzie się na moim komputerze, ponieważ łatka została zainstalowana jako część narzędzi (# 2). Nie byłem jeszcze świadkiem sytuacji nr 3.

Jaki jest lepszy sposób na wykrycie, czy plaster został zastosowany?

Odpowiedz

13

Win32_QuickFixEngineering nie zwróci wszystkich aktualizacji. Właściwie, to zwraca tylko ograniczone do aktualizacji QFE:

aktualizacji dostarczanych przez Microsoft Windows Installer (MSI) lub witrynie Windows Update (http://update.microsoft.com) nie są zwracane przez Win32_QuickFixEngineering.

Aktualizacja, której szukasz, to łatka MSI. Użyj Microsoft.Deployment.WindowsInstaller (aka DTF - Deployment Tools Foundation, część WiX toolset) kwerendy zastosowane poprawki 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); 
} 

W tym przypadku KB2468871 jest jednym z .NET Framework 4 aktualizacji. Poniższa zwróci true, jeśli aktualizacje zostały zastosowane w urządzeniu:

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 
+0

Weryfikujemy to podejście. Dziękuję za Twoją odpowiedź! –

10

Grałem około z podobnej sytuacji i okazało @KMoraz jest odpowiedź na prawie rację. (UWAGA: @KMoraz, pozostawiłbym to jako komentarz, ale nie mam jeszcze rep!) ​​

Wygląda na to, że przestrzeń nazw Microsoft.Deployment.WindowsInstaller jest sposobem na to, ale filtrowanie według kodu produktu może być zbyt restrykcyjne. Wystąpił problem polegający na tym, że łatka została zainstalowana na komputerze, ale nie jest związana z kodem produktu {F5B09CFD-F0B2-36AF-8DF4-1DF6B63FC7B4} lub {8E34682C-8118-31F1-BC4C-98CD9675E1C2}.

Moim rozwiązaniem było zamiast tego użycie PatchInstallation.AllPatches, która zwraca niefiltrowaną listę zainstalowanych poprawek w systemie, a następnie poszukaj odpowiedzi za pomocą linq.Wyjście

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

Próbka:

--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} 
+0

Właśnie kierowałem pytanie OP ... W każdym razie, dzięki za twój post - zaktualizowałem go o 32-bitowe identyfikatory GUID. – KMoraz

+0

Nice. Twoja odpowiedź wygląda dobrze i była bardzo pomocna. – jstromwick

10

W przypadku ktoś wciąż stara się zrobić to w 2015 roku, I to osiągnąć z WiX Tajne stosując następujący fragment (przy użyciu kodów produktów z @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> 

namespace util dotyczy Wix Util Extension. Będziesz potrzebował xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" w swoim głównym elemencie i odniesienie do WixUtilExtension.dll.

Instalatory zostaną automatycznie pobrane w razie potrzeby. Musisz mieć pliki instalatora zapisane lokalnie w katalogu głównym projektu WiX o tej samej nazwie, która została określona przez SourceFile do jej zbudowania, ale nie zostaną dodane do pakietu instalacyjnego, ponieważ Compressed jest ustawione na no.