visual - Actualice la función individual en el árbol de características de WIX sin desinstalar/actualizar otras características
wix visual studio 2015 (2)
Parece que descubrió el escenario de actualización, ahora solo necesita averiguar dónde colocar RemoveExistingProducts en una actualización importante de MSI para que las características no se reinstalen si no han cambiado :)
Intento crear un proyecto de instalación usando WIX que me permita instalar múltiples características de un solo producto. ¿Cómo puedo actualizar una de las características instaladas (que es independiente de las otras características instaladas) sin tener que volver a instalar las otras funciones en el árbol de características?
Por ejemplo, quiero poder tener un proyecto (volviendo a HelloWolrd) llamado HelloWolrd, que (sorpresa) imprime "¡Hola mundo!" en la pantalla. Digamos que tengo tres de estas aplicaciones Hello World, Hello World 1, Hello World 2 y Hello World 3. Cada una de ellas se imprime respetuosamente en la pantalla Hello World 1, 2 o 3. Lo que me gustaría es crear una MSI que de forma predeterminada instale estas tres "características", pero también permite la actualización de cada característica individualmente en un momento posterior.
Aquí está mi diseño de mi solución:
Solution Explorer http://img12.imageshack.us/img12/5671/solutionexplorerm.jpg
Mi archivo WIX Product.wxs se ve así:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="ca484210-c719-4b2e-b960-45212d407c11" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0" Manufacturer="HelloWorldInstaller" UpgradeCode="68eeb8cb-9ef3-443c-870c-9b406129f7ff">
<Package InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<!-- Create Directory Structure -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="Hello World" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop"/>
</Directory>
<DirectoryRef Id="INSTALLLOCATION">
<Component Id="HelloWorld1" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
<RegistryKey Root="HKCU" Key="Software/HelloWorldInstaller/HelloWorld1/Install" Action="createAndRemoveOnUninstall">
<RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
</RegistryKey>
<File Id="HelloWorld1.exe" Name="$(var.HelloWorld1.TargetFileName)" Source="$(var.HelloWorld1.TargetPath)" DiskId="1" Checksum="yes">
<Shortcut Id="HelloWorld1ApplicationDesktopShortcut" Name="Hello World 1" Description="Hello World Application 1" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
</File>
</Component>
<Component Id="HelloWorld2" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
<RegistryKey Root="HKCU" Key="Software/HelloWorldInstaller/HelloWorld2/Install" Action="createAndRemoveOnUninstall">
<RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
</RegistryKey>
<File Id="HelloWorld2.exe" Name="$(var.HelloWorld2.TargetFileName)" Source="$(var.HelloWorld2.TargetPath)" DiskId="1" Checksum="yes">
<Shortcut Id="HelloWorld2ApplicationDesktopShortcut" Name="Hello World 2" Description="Hello World Application 2" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
</File>
</Component>
<Component Id="HelloWorld3" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
<RegistryKey Root="HKCU" Key="Software/HelloWorldInstaller/HelloWorld3/Install" Action="createAndRemoveOnUninstall">
<RegistryValue Name="DTSC" Value="1" Type="integer" KeyPath="yes" />
</RegistryKey>
<File Id="HelloWorld3.exe" Name="$(var.HelloWorld3.TargetFileName)" Source="$(var.HelloWorld3.TargetPath)" DiskId="1" Checksum="yes">
<Shortcut Id="HelloWorld3ApplicationDesktopShortcut" Name="Hello World 3" Description="Hello World Application 3" Directory="DesktopFolder" WorkingDirectory="INSTALLLOCATION" />
</File>
</Component>
</DirectoryRef>
<Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
<ComponentRef Id="HelloWorld1"/>
</Feature>
<Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
<ComponentRef Id="HelloWorld2"/>
</Feature>
<Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
<ComponentRef Id="HelloWorld3"/>
</Feature>
</Product>
</Wix>
Ahora, cuando se compila, instala las características como era de esperar. Sin embargo, cuando realiza una modificación en HelloWorld1.vb y recompila, me gustaría que reinstale (actualice) solo esa característica, no todas.
Cuando actualizo un archivo y reconstruyo la solución, intento instalar el msi, obtengo este error:
Error de MSI http://img696.imageshack.us/img696/849/anotherversionisinstall.jpg
Actualicé mi código para permitir la desinstalación de las características y permitir el uso de códigos de actualización, pero eso desinstaló todas las características y las reinstalé todas.
- Aplicación del mundo real -
La aplicación del mundo real a esto es un gran paquete de software que necesita múltiples aplicaciones de soporte que se ejecutan como servicios / tareas programadas de forma regular. Me gustaría obtener la instalación de estas aplicaciones de soporte en una MSI, lo que nos permite no tener una pesadilla tan grande como la de desplegar cada uno de ellos de manera individual. Sé que si tenemos una actualización de uno de los exe que podríamos compilar manualmente ese exe y ponerlo en funcionamiento, pero me gustaría hacer esto de una manera completamente reproducible.
Cualquier ayuda será apreciada,
¡Gracias!
EDITAR:
Agregué la fuente para descargar de Google Code . ¡Gracias de nuevo!
Entendí esto y pensé que publicaría la respuesta aquí para referencia futura para otros. Entonces, he explicado completamente el problema, entraré en una situación más profunda del mundo real.
Tenemos una pieza de software moderadamente grande que requiere que tengamos múltiples aplicaciones de soporte que se ejecutan en varios servidores diferentes. Nuestra progresión actual de actualizaciones hace que sea moderadamente difícil actualizar el código de manera confiable. Actualmente usamos exe autoextraíble para implementar nuestro código en los diferentes servidores. El problema surge cuando tenemos una cantidad tan grande de aplicaciones de soporte que es difícil asegurarnos de que las aplicaciones se instalaron correctamente con la configuración de configuración correcta, etc. Para resolver este problema, estamos estudiando la posibilidad de en lugar de comprimir cada una de ellas. En las aplicaciones de soporte, creamos un instalador único (MSI) que permitirá al equipo de infraestructura instalar un conjunto específico de aplicaciones de soporte para cada máquina. Cuando tengamos un cambio importante (por ejemplo, de 1.0 a 2.0) haremos una instalación de actualización completa (lo que significa que todos los servicios / procesos deberán detenerse, desinstalarse, instalarse e iniciarse). Cuando tengamos un cambio menor, solo nos gustaría tener que detener y volver a instalar los servicios / procesos afectados, sin tocar otras aplicaciones. Ahora, basta de mi divagación, vayamos a la solución:
Modifiqué WIX Product.wxs para eliminar los accesos directos, ya que realmente no los necesitamos en nuestro escenario. Aquí está el archivo wxs actualizado:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="13C373D3-5C27-487e-A020-C2C89E4607B1" Name="HelloWorldInstaller" Language="1033" Version="1.0.0.0"
Manufacturer="HelloWorldInstaller" UpgradeCode="E7CB3C76-4D51-48a8-BFB4-6D11B2E2E65B">
<Package InstallerVersion="200" Compressed="yes" />
<Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
<FeatureRef Id="HelloWorld1Feature" />
<FeatureRef Id="HelloWorld2Feature" />
<FeatureRef Id="HelloWorld3Feature" />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="Hello World" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop"/>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="INSTALLLOCATION">
<Directory Id="HelloWorld1Directory" Name="Hello World 1">
<Component Id="HelloWorld1Component" Guid="6D1D9D33-DA17-4db3-8132-C39F32200C3A">
<File Id="HelloWorld1.exe" Name="HelloWorld1.exe" Source="HelloWorld1.exe" DiskId="1" Checksum="yes" />
</Component>
</Directory>
<Directory Id="HelloWorld2Directory" Name="Hello World 2">
<Component Id="HelloWorld2Component" Guid="B2D51F85-358B-41a7-8C45-B4BB341158F8">
<File Id="HelloWorld2.exe" Name="HelloWorld2.exe" Source="HelloWorld2.exe" DiskId="1" Checksum="yes" />
</Component>
</Directory>
<Directory Id="HelloWorld3Directory" Name="Hello World 3">
<Component Id="HelloWorld3Component" Guid="A550223E-792F-4169-90A3-574D4240F3C4">
<File Id="HelloWorld3.exe" Name="HelloWorld3.exe" Source="HelloWorld3.exe" DiskId="1" Checksum="yes" />
</Component>
</Directory>
</DirectoryRef>
</Fragment>
<Fragment>
<Feature Id="HelloWorld1Feature" Title="Hello World 1" Level="1">
<ComponentRef Id="HelloWorld1Component"/>
</Feature>
</Fragment>
<Fragment>
<Feature Id="HelloWorld2Feature" Title="Hello World 2" Level="1">
<ComponentRef Id="HelloWorld2Component"/>
</Feature>
</Fragment>
<Fragment>
<Feature Id="HelloWorld3Feature" Title="Hello World 3" Level="1">
<ComponentRef Id="HelloWorld3Component"/>
</Feature>
</Fragment>
</Wix>
Ahora, junto con esto, para nuestras actualizaciones menores, buscaremos liberar parches para nuestros componentes.
Por ejemplo, supongamos que tenemos un ProductA, que tiene tres componentes: 1,2 y 3. Estos tres componentes deben ejecutarse como servicios o tareas programadas. Debido a la naturaleza de nuestro producto, no podemos cerrar todos nuestros servicios para actualizar o corregir uno de nuestros componentes. Entonces, si después de que hemos instalado la versión 1.0, encontramos un error en el componente 2, pero no queremos que 1 o 3 se vean afectados por la corrección que se aplica a este error, lanzaremos un parche para el componente 2, por lo tanto, solo el componente 2 se verá afectado.
Para nuestro ejemplo rápido anterior, estamos utilizando HelloWorld1, HelloWorld2 y HelloWorld3 como nuestros 3 componentes en nuestra aplicación de software. La idea es que deberíamos poder instalar los tres con un MSI, pero luego actualizar cada uno de forma independiente sin que afecte a ninguno de los otros componentes instalados.
Entonces, para demostrar esto, he creado las tres aplicaciones de la consola de arriba que mostrarán "Hello World 1!", "Hello World 2!" Y "Hello World 3!". Luego, después de que lanzamos el MSI inicial, digamos que encontramos un "error" que requiere que HelloWorld1 diga "¡Hola mundo 1! Actualizado". en lugar. Esto es lo que haremos para simular esto:
- Cree el Product.wixobj ejecutando este comando en el símbolo del sistema:
candle.exe Product.wxs
Recuerde que para llamar a candle.exe o cualquiera de los comandos WIX, el directorio de instalación de Wix debe estar en su variable PATH. ( Tutorial breve sobre la actualización de la variable de entorno PATH ) Además, realice los comandos en el mismo directorio que su archivo Product.wxs. - Crea la primera versión de tu producto (digamos 1.0):
light.exe Product.wixobj -out ProductA-1.0.msi
- Ahora encuentre un error (cambie la salida de HelloWorld1 para decir "¡Hola Mundo 1! Actualizado.") Luego actualice la versión de ensamblaje y la versión de archivo . Esto es importante ya que así es como WIX puede decir que los exe son diferentes.
- Ejecute el mismo comando que el paso uno (para una buena medida):
candle.exe Product.wxs
- Ejecute casi el mismo comando que el paso dos:
light.exe Product.wixobj -out ProductA-1.1.msi
Tenga en cuenta que esta es la versión 1.1 en lugar de 1.0 (este es el msi con nuestro código actualizado). Sin embargo, no queremos simplemente instalar esto, seguir leyendo. - Aquí está la parte divertida, obtenemos la diferencia en los dos MSI con el siguiente comando:
torch.exe -p -xi ProductA-1.0.wixpdb ProductA-1.1.wixpdb -out Diff.WixMst
- Ahora creamos el archivo de parche a partir de esto (Patch.wxs se explicará a continuación):
candle.exe Patch.wxs
- Ahora crearemos el archivo WixMsp con este comando:
light.exe Patch.wixobj -out Patch.WixMsp
- Y ahora, la parte divertida. Crea el archivo MSP con este comando:
pyro.exe Patch.WixMsp -out Patch.msp -t RTM Diff.Wixmst
Ahora, si todo fue según lo planeado, debería tener dos archivos msi y uno msp. Si instala el primer msi (ProductA-1.0.msi) y ejecuta HelloWorld1.exe, debería ver el mensaje "Hello World 1!". Solo por diversión (y ejemplo), ejecute las otras aplicaciones y déjelas en ejecución (construí una parada para mantenerlas abiertas). Cierre HelloWorld1.exe ya que ahora vamos a aplicar la actualización para ese exe, pero al hacerlo no afectaremos a HelloWorld2.exe o HelloWorld3.exe. Si ahora instala el archivo msp (Patch.msp) y luego ejecuta HelloWorld1.exe, verá el mensaje actualizado, "Hola, mundo 1, actualizado".
Ahora, para el archivo mágico Patch.wxs:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="yes"
Manufacturer="Dynamo Corp"
MoreInfoURL="http://www.dynamocorp.com/"
DisplayName="Sample Patch"
Description="Small Update Patch"
Classification="Update"
>
<Media Id="5000" Cabinet="RTM.cab">
<PatchBaseline Id="RTM"/>
</Media>
<PatchFamilyRef Id="SamplePatchFamily"/>
</Patch>
<Fragment>
<PatchFamily Id=''SamplePatchFamily'' Version=''1.0.0'' Supersede=''yes''>
<ComponentRef Id="HelloWorld1Component"/>
</PatchFamily>
</Fragment>
</Wix>
No parece mucho, ¿verdad? Bueno, las partes más interesantes son estas:
-
<PatchBaseline Id="RTM"/>
- Esto si lo recuerdas se usa en nuestra creación del parche msi. El "RTM" se menciona en el último paso anterior:-t RTM
- Estos tienen que coincidir. -
<ComponentRef Id="HelloWorld1Component"/>
- Esto apunta al parche al componente correcto para actualizar, en nuestro caso HelloWorld1Component.
Si ha estado buscando por todas partes, el código anterior puede parecerle familiar porque proviene del Blog de Peter Marcu : WiX: Creación de un parche utilizando el nuevo Patch Building System - Parte 3
También confié mucho en el Blog de Alex Shevchuk : de MSI a WiX, Parte 8 - Mejora importante
Si te estás preguntando, "Guau, son muchos los pasos, ¿por qué alguien haría estos muchos pasos?", Recuerda que una vez que hayas terminado el trabajo (arriba), debes mover esto a tu rutina de integración. ¡Eso es correcto, integrar, integrar, integrar ! ¿Cómo haces esto? Bueno, eso es un poco más de investigación, ¿y tal vez una publicación de blog? - Probablemente. Para comenzar con el pie derecho, aquí hay un artículo impresionante sobre Versiones automatizadas con MSBuild y Windows Installer XML .
Guau, espero que lean todo esto (los dos), y aprendieron mucho. Espero que esto ayude a alguien que no sea yo.