2012-02-28 9 views
15

Nuestro instalador de WiX implementa una aplicación .NET 4.0 WinForms para Windows Vista y 7 escritorios. La aplicación incluye un Portable Class Library que requiere un .NET patch (KB2468871). Necesitamos instalar el parche como un requisito previo. Hay varias maneras de que el parche se puede aplicar:Detecta y requiere un Windows QFE/parche durante la instalación

  1. Descargar el parche KB2468871 e instalarlo
  2. Instalar el Portable Library Tools
  3. Como requisito previo mediante ClickOnce (podría ser una variación de # 1)

Usando el asesoramiento de a similar question, creé un CustomAction para verificar el QFE (n. ° 1) que demostré. Devuelve verdadero cuando se encuentra.

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

Por desgracia, esto no funciona en mi máquina dev como el parche se ha instalado como parte de las herramientas (# 2). No he sido testigo de la situación n. ° 3 todavía.

¿Cuál es una mejor manera de detectar si se aplicó el parche?

Respuesta

13

Win32_QuickFixEngineering no devolverá todas las actualizaciones. En realidad, devuelve sólo las actualizaciones restringidas a QFE:

actualizaciones proporcionadas por Microsoft Windows Installer (MSI) o en el sitio de actualización de Windows (http://update.microsoft.com) no son devueltos por Win32_QuickFixEngineering.

La actualización que está buscando es un parche de MSI. Utilice Microsoft.Deployment.WindowsInstaller (también conocido como DTF - Deployment Tools Foundation, parte de la WiX toolset) para consultar los parches aplicados 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); 
} 

En este caso, KB2468871 es uno de .NET Framework 4 actualizaciones. El siguiente devolverá verdadero si las actualizaciones se han aplicado en la máquina:

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

Estamos verificando este enfoque. ¡Gracias por su respuesta! –

10

He estado jugando con una situación similar y se encontró @KMoraz 's respuesta sea casi justo. (NOTA: @KMoraz, dejaría esto como un comentario, pero no tengo la rep aún!)

El espacio de nombre Microsoft.Deployment.WindowsInstaller parece ser el camino a seguir, pero el filtrado por código de producto puede ser demasiado restrictivo. Me encontré con un problema donde el parche se instaló en una máquina, pero no se asoció con ninguno de los códigos de producto {F5B09CFD-F0B2-36AF-8DF4-1DF6B63FC7B4} o {8E34682C-8118-31F1-BC4C-98CD9675E1C2}.

Mi solución fue utilizar en su lugar PatchInstallation.AllPatches, que devuelve una lista no filtrada de parches instalados en el sistema, luego busque la respuesta utilizando linq.salida

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

muestra:

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

Solo estaba enfocando la pregunta del OP ... De todos modos, gracias por su publicación, la actualicé con los GUID de 32 bits. – KMoraz

+0

Agradable. Tu respuesta se ve bien y fue muy útil. – jstromwick

10

En el caso de cualquier otra persona todavía está tratando de hacer esto en 2015, que logra esto con WiX Burn utilizando el siguiente fragmento (utilizando los códigos de producto de @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> 

el util espacio de nombres se refiere a la Wix Util Extension. Necesitará un xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" en su elemento raíz y una referencia al WixUtilExtension.dll.

Los instaladores se descargarán automáticamente si es necesario. Debe tener los archivos del instalador guardados localmente en la raíz de su proyecto de WiX con el mismo nombre especificado por SourceFile para que se compile, pero no se agregarán al paquete de configuración porque Compressed está establecido en no.

Cuestiones relacionadas