c # - Opdag og kræve en Windows QFE/patch til under installationen

Indlæg af Hanne Mølgaard Plasc

Problem



Vores WiX-installatør anvender en. NET 4.0 WinForms-applikation til Windows Vista og 7 desktops. Programmet indeholder et bærbart klassebibliotek, der kræver en .NET-patch (KB2468871). Vi skal installere plaster som en forudsætning. Der findes forskellige måder at lappen kan anvendes på: [20] [21]



  1. Download KB2468871 programrettelsen og installer den

  2. Installer de bærbare bibliotekværktøjer

  3. Som en forudsætning ved at bruge ClickOnce (kan være en variant af # 1)



Ved hjælp af råd fra et lignende spørgsmål oprettede jeg en CustomAction for at kontrollere QFE (# 1), som jeg viste returnerer sandt, når den blev fundet. [22]


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


Desværre mislykkes dette på min dev-maskine, da plåstret blev installeret som en del af Værktøjerne (# 2). Jeg har ikke oplevet situation nr. 3 endnu.


Hvad er en bedre måde at opdage, hvis lappen er blevet anvendt?

Bedste reference


Win32\_QuickFixEngineering vil ikke returnere alle opdateringer. Faktisk returnerer den kun opdateringer, der er begrænset til QFE: [24]



  Opdateringer leveret af Microsoft Windows Installer (MSI) eller Windows
  opdateringswebsted (http://update.microsoft.com) returneres ikke af
  Win32\_QuickFixEngineering.



Opdateringen du følger er en MSI-patch. Brug Microsoft.Deployment.WindowsInstaller (også DTF - Deployment Tools Foundation , en del af WiX værktøjssæt ) for at søge de anvendte MSI-patches: [25] [26]


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


I dette tilfælde er KB2468871 en af ​​.NET Framework 4-opdateringer. Følgende vil returnere sande, hvis opdateringerne er blevet anvendt på maskinen:


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

Andre referencer 1


Hvis nogen andre stadig forsøger at gøre dette i 2015, opnåede jeg dette med WiX Burn ved hjælp af følgende fragment (ved hjælp af produktkoderne fra @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>


Navnet på util henviser til Wix Util Extension. Du skal bruge en xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" i dit rodelement og en henvisning til WixUtilExtension.dll. [27]


Installatørerne downloades automatisk, hvis det kræves. Du skal have installeringsfilerne gemt lokalt i roden af ​​dit WiX-projekt med samme navn som angivet af SourceFile for at det skal opbygges, men de vil ikke blive tilføjet til installationspakken fordi Compressed er indstillet til no.

Andre referencer 2


Jeg har spillet rundt med en lignende situation og fandt @KMorazs svar til at være næsten ret. (BEMÆRK: @KMoraz, jeg ville forlade dette som en kommentar, men har ikke repen endnu!)


Navnet på Microsoft.Deployment.WindowsInstaller ser ud til at være vejen at gå, men filtrering efter produktkode kan være for restriktiv. Jeg har kørt ind i et problem, hvor lappen blev installeret på en maskine, men ikke forbundet med enten produktkode {F5B09CFD-F0B2-36AF-8DF4-1DF6B63FC7B4} eller {8E34682C-8118-31F1-BC4C-98CD9675E1C2}.


Min løsning var i stedet at bruge PatchInstallation.AllPatches, som returnerer en ufiltreret liste over installerede patches på systemet, så søg efter svaret ved hjælp af 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);
}


Prøveudgang:


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