wix windows-installer

La actualización de Wix Tools usa acciones personalizadas antiguas



windows-installer (2)

descubrimos algunos comportamientos extraños con las herramientas de configuración de WIX. Hemos implementado algunas versiones principales (2.2.0 - a 2.2.4). Para 2.2.5 cambiamos cosas pequeñas en acciones personalizadas (antes de usar XCOPY, ahora usamos RoboCopy porque tiene un comando "MOVER" y no solo una copia).

Pero cuando ahora actualizamos de 2.2.4 a 2.2.5, la configuración todavía usa el antiguo comando Copiar en lugar del nuevo comando MOVE, pero esto no puede ser porque 2.2.5 no tiene ningún comando Copiar. Si despliego un 2.2.6 (idéntico a 2.2.5) y actualizo desde 2.2.5, usa el nuevo proceso de actualización ... Parece que la actualización usa el antiguo MSI.

Encontré esto en SO

¿Hay alguna forma de prevenir este comportamiento? Esto interrumpe completamente el proceso de actualización ya que los archivos de configuración existentes no se copian correctamente en la actualización.

No podemos obligar al cliente a limpiar el registro o eliminar cualquier archivo MSI del caché del formulario por GUID ...

Cualquier ayuda apreciada. Gracias por adelantado

ACTUALIZACIÓN: Nueva acción personalizada en Product.wxs

<Property Id="C_TEMP" Value="C:/Temp" /> <Property Id="ROBOCOPY_EXE">robocopy.exe</Property> <CustomAction Id="CopyToTemp" Property="ROBOCOPY_EXE" Return="ignore" ExeCommand=''"[INSTALLDIR]/Configuration" "[C_TEMP]/ServerSettings" ServerSettings.json'' /> <CustomAction Id="CopyFromTemp" Property="ROBOCOPY_EXE" Return="ignore" ExeCommand=''"[C_TEMP]/ServerSettings" "[INSTALLDIR]/Configuration" ServerSettings.json /MOVE /IS'' />

Antigua acción personalizada

<Property Id="C_TEMP" Value="C:/Temp" /> <Property Id="XCOPY_EXE">xcopy.exe</Property> <CustomAction Id="CopyToTemp" Property="XCOPY_EXE" Return="ignore" ExeCommand=''"[INSTALLDIR]/Configuration/ServerSettings.json" "[C_TEMP]/ServerSettings.json.bak*" /YIR'' /> <CustomAction Id="CopyFromTemp" Property="XCOPY_EXE" Return="ignore" ExeCommand=''"[C_TEMP]/ServerSettings.json.bak" "[INSTALLDIR]/Configuration/ServerSettings.json*" /YIR'' />

Luego el código no cambió hasta ahora

<InstallExecuteSequence> <Custom Action="CopyToTemp" Before="InstallInitialize">Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)</Custom> <Custom Action="CopyFromTemp" Before="SetVersionsInRegistry">NOT Installed OR Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)</Custom> ..... </InstallExecuteSequence>


Prueba de las condiciones

Condición # 1:

Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

Esta constelación de condicionamiento bastante extraña hará que la acción personalizada en cuestión no se ejecute durante una instalación nueva, ni una desinstalación manual. Parece que esta acción personalizada se ejecutará durante: actualización importante (que es un tipo especial de desinstalación), modificación y reparación. Supongo que esto haría el trabajo de hacer una copia de seguridad del archivo de configuración. Sin embargo...

Durante una actualización importante, esto parecería que la acción personalizada anterior se está ejecutando, porque lo que se está ejecutando es su paquete anterior en modo de actualización principal (que es un tipo especial de desinstalación), por lo tanto, presenta las acciones personalizadas del paquete anterior ( lo que se está ejecutando es la antigua base de datos en caché de su instalación anterior; se desinstala como parte de la actualización principal ). Estas acciones personalizadas nunca se ejecutaron durante la instalación inicial del paquete. Pero su otra acción personalizada para copiar de temp will. Probablemente ese no sea el comportamiento correcto.

Para resumir:

  • Ejecuciones : actualización importante (ejecutada a través del antiguo MSI que desinstala, pero no en el nuevo MSI), modificar, reparar
  • No se ejecuta : primera instalación, desinstalación.

Condición # 2:

NOT Installed OR Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

La segunda condición, que también es un poco exótica, parece ejecutarse en una instalación nueva y solo en una actualización importante. Probablemente solo lo necesite para ejecutarse durante una actualización importante, pero ¿no debería también ejecutarse durante la reparación y modificación? (estos modos también pueden sobrescribir el archivo de configuración en ciertos casos, como cuando REINSTALLMODE está configurado en " amus " para forzar la sobrescritura de archivos).

Para resumir:

  • Se ejecuta : instalación por primera vez, actualización importante
  • No se ejecuta : desinstalar, modificar, reparar

Condiciones estándar

Realmente no tengo una idea completa de todo su escenario, pero puede encontrar un par de enlaces a recursos para encontrar condiciones comunes aquí : ¿Es posible ejecutar una acción personalizada solo en modo de reparación ? Supongo que desea hacer una copia de seguridad del archivo de configuración en las principales actualizaciones, reparaciones y modificaciones para evitar que se sobrescriba. ¿Parece que las condiciones deberían modificarse un poco para lograr esto?

Recomendaría evitar por completo las acciones personalizadas, y a continuación se presentan algunos enfoques sugeridos para lograr esto.

Uso de la aplicación para administrar archivos de configuración

La administración y configuración de los archivos de configuración siempre ha sido un problema difícil de implementación. Hace unos días escribí un breve resumen de las diferentes formas de lidiar con los archivos de configuración del usuario: Crear carpeta y archivo en el perfil de usuario actual, desde el perfil de administrador (es una pequeña referencia de las diferentes formas de implementar archivos de configuración - recomendado, y por favor avíseme si no está claro).

Como se puede ver en la respuesta vinculada anteriormente, a menudo es una buena idea usar su aplicación para inicializar los archivos de configuración de las copias de plantillas que instala su instalación en una ubicación de solo lectura en INSTALLDIR. Luego, dejaría la plantilla sin cambios, pero al iniciar su aplicación copiará el archivo de configuración de su plantilla en el perfil de usuario de cada usuario, o simplemente creará una copia en INSTALLDIR que el proceso de instalación nunca tocará (necesitaría aplicar permisos ACL para hacer esto archivo de configuración que pueden escribir todos los usuarios; no es un diseño excelente, pero funciona). Este enfoque basado en plantillas separa el archivo de configuración de las consideraciones de implementación. Nunca se reiniciará, desinstalará ni interferirá a partir de ahora, ya que nunca fue instalado por la configuración . De hecho, debe implementar su limpieza o desinstalación específicamente (por ejemplo, mediante una construcción RemoveFolder / RemoveFile), o permanecerá en el disco al desinstalar, lo que también puede ser un problema.

Siempre es una ventaja evitar la compleja arquitectura de Windows Installer para tratar acciones personalizadas. Hay suplantación compleja , condicionamiento complejo , secuenciación compleja y también dependencias de tiempo de ejecución para varios binarios a los que llama. ¿Está utilizando DTF o simplemente un conjunto C # directo para llamar? Hay algunos problemas con el uso de acciones personalizadas administradas (versión CLR incorrecta cargada, no hay .NET instalado (¿bloqueado?), Dependencias de los archivos en el GAC, etc. No tengo una descripción completa: me quedo lejos de todo el código administrado para la implementación de MSI por estos motivos).

Al copiar archivos de configuración de plantilla a un nuevo archivo que su instalador no pueda tocar, no tendrá que lidiar con los caprichos y peculiaridades de MSI, ni con ninguna acción personalizada administrada y sus requisitos de tiempo de ejecución.

ACTUALIZACIÓN : elimino el enfoque transitivo que agregué antes después de que más pruebas revelaran que solo funcionará en ciertos casos. Lo revisaré nuevamente usando una actualización menor en lugar de una actualización mayor. Luego, podría usar un parche de actualización menor para migrar toda la versión anterior para establecer el archivo de configuración de forma permanente para que nunca se desinstale nuevamente, y luego aplicaría su actualización principal. Esto debería ser posible para envolver en un programa de arranque Burn .

ACTUALIZACIÓN : como se supone (y verificado) una actualización menor puede cambiar cualquier componente a permanente y no hay necesidad de usar ninguna configuración transitiva para el componente (no verifiqué si una actualización menor puede cambiar un componente para que no sea permanente si se estableció permanente antes). De hecho, habilitar transitivo en realidad podría desinstalar el componente si cualquier condición asociada al componente se evalúa como falsa durante la instalación; no lo verifiqué, pero tiene sentido lógico que pueda ser posible. Lo primero que viene a la mente es si esto podría desinstalar un conjunto de componentes a permanente. No debería, pero he visto tanta rareza antes con MSI. Puedo imaginar esto necesario para un conjunto de componentes implementado permanentemente en System32, por ejemplo. En conclusión: si todo lo que necesita es preservar un archivo de configuración, simplemente use una actualización menor para configurarlo de forma permanente y luego puede usar las actualizaciones importantes nuevamente. No establezca el componente transitivo.

Solo por mencionarlo: su archivo de configuración de hecho no está siendo sobrescrito por su actual esquema de actualización por cierto. Se está desinstalando y reinstalando durante la actualización principal porque su componente no se configuró originalmente como Permanent = "yes" y NeverOverwrite="yes" . Esto parece haberlo revertido a los valores predeterminados, pero nunca se sobrescribió. Más bien se desinstaló y reinstaló eliminando los cambios. MSI no sobrescribirá los archivos modificados no versionados, pero los desinstalará y reinstalará a menos que estén marcados como permanentes. En mi opinión , es un antipatrón tecnológico : muchos equipos se enfrentan a este problema todo el tiempo. De ahí mi sugerencia de revisar algunas opciones de implementación de archivos de datos como se describe aquí: Crear carpeta y archivo en el perfil de usuario actual, desde el perfil de administrador (mismo enlace que el anterior).

Espero que algo de esto ayude, y háganos saber lo que encuentra durante las pruebas.

ANTIGUA RESPUESTA :

Brian mencionó el consejo real, pero tal vez algunas preguntas para aclarar. Desarrollaré esto en un intento de respuesta una vez que tenga algunas respuestas.

  • ¿Cómo se ejecutan estas acciones personalizadas? ¿Son comandos EXE o estás ejecutando un EXE lanzador que luego los invoca? Si utiliza un EXE de este tipo, ¿es nativo (C ++) o .NET? (C # / VB.NET). Si es .NET, a menudo son malas noticias.
  • ¿Podemos preguntarle qué está haciendo con estos comandos de copia? ¿Podría hacerse esto en la aplicación misma de manera más confiable? Este es quizás el consejo más común que le damos a la gente, que si se sigue puede simplificar drásticamente la implementación y hacerla más confiable. Tiene más control de lo que sucede en una aplicación, se ejecuta en un contexto de seguridad predecible y no hay que condicionar ni secuenciar. Y finalmente: puede reiniciar la aplicación y volver a hacerlo, una configuración es "one shot".
  • Lo dejaré así por ahora ...

Debe ser más específico sobre lo que quiere decir con "actualización" porque podría ser un parche, una actualización menor, una actualización importante. Si es una actualización importante, debe decir dónde está secuenciada. Sin embargo, hay dos razones generales por las que podrían ejecutarse acciones personalizadas de una versión anterior:

  1. Comentario / respuesta de Brian: se condicionaron incorrectamente en esa instalación original, y cuando la actualización pasa por las secuencias en la instalación anterior, descubre que la condición se evalúa como verdadera. Si lo desea, no existen cosas como instalar acciones personalizadas o desinstalar acciones personalizadas: solo hay acciones personalizadas con condiciones. En la fuente de WiX que se publicó como una actualización, el uso de UPGRADINGPRODUCTCODE no es correcto. Esta propiedad se establece en el producto anterior cuando se desinstala durante una actualización importante, por lo que cualquier condición en la instalación anterior que diga "o UPGRADINGPRODUCTCODE" será verdadera. Si desea una condición establecida en la instalación de actualización cuando está actualizando un producto anterior, use WIX_UPGRADE_DETECTED, como lo usa el elemento MajorUpgrade.

  2. El acto de realizar una actualización ha provocado una reparación del producto anterior y, por lo tanto, ha ejecutado las acciones personalizadas, e incluso podrían tener una condición correcta. Si, por ejemplo, un archivo binario ha sido reemplazado y es candidato para el reemplazo durante su actualización, Windows Installer reparará y restaurará el binario que no coincida para que pueda decidir si instala el archivo de la actualización. Esto reinstalará la característica que contiene ese binario. Por lo tanto, podrían ejecutarse acciones personalizadas condicionadas a la instalación de características o componentes.

Además, para extender la respuesta de Stein, Windows Installer y WiX tienen un movimiento (vea el elemento CopyFile). ¿Y por qué instalar un archivo en una ubicación e inmediatamente moverlo a otra ubicación? ¿Asumo que hay una razón para no simplemente instalarlo y la ubicación final sin hacer un movimiento?