¿Cómo agregar una acción personalizada de WiX que solo ocurre en la desinstalación (a través de MSI)?

Me gustaría modificar un instalador de MSI (creado a través de WiX ) para eliminar un directorio completo en la desinstalación.

Entiendo las opciones RemoveFile y RemoveFolder en WiX, pero estas no son lo suficientemente robustas como para eliminar de forma recursiva una carpeta completa que tenga contenido creado después de la instalación.

Observé la pregunta similar sobre el desbordamiento de stack. Eliminé archivos al desinstalar WiX , pero me preguntaba si esto podría hacerse de forma más simple utilizando una llamada a un script por lotes para eliminar la carpeta.

Esta es la primera vez que uso WiX, y todavía me estoy acostumbrando a las acciones personalizadas . ¿Cuál sería un ejemplo básico de una acción personalizada que ejecutará un script por lotes en la desinstalación?

EDITAR : Quizás mire la respuesta inmediatamente debajo.


Este tema ha sido un dolor de cabeza por mucho tiempo. Finalmente lo resolví. Hay algunas soluciones en línea, pero ninguna de ellas realmente funciona. Y, por supuesto, no hay documentación. Por lo tanto, en el cuadro a continuación hay varias propiedades que se sugieren usar y los valores que tienen para varios escenarios de instalación:

texto alternativo

Entonces, en mi caso, quería una CA que se ejecutará solo en las desinstalaciones, no en las actualizaciones, ni en las reparaciones ni en las modificaciones. De acuerdo con la tabla anterior, tuve que usar

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

¡Y funcionó!

Hay múltiples problemas con la respuesta de yaluna , también los nombres de las propiedades distinguen entre mayúsculas y minúsculas, Installed es la ortografía correcta ( INSTALLED no funcionará). La tabla de arriba debería haber sido esta:

enter image description here

Además, suponiendo una reparación y desinstalación completa, los valores reales de las propiedades podrían ser:

enter image description here

La documentación de syntax de expresiones de WiX dice:

En estas expresiones, puede usar nombres de propiedad (recuerde que son sensibles a las mayúsculas y minúsculas).

Las propiedades están documentadas en la Guía del instalador de Windows (por ejemplo, instalada )

EDITAR: pequeña corrección en la primera tabla; evidentemente, “Desinstalar” también puede suceder con solo REMOVE siendo True .

Puedes hacer esto con una acción personalizada. Puede agregar una referencia a su acción personalizada en :

  ...  Installed AND NOT UPGRADINGPRODUCTCODE 

Luego también deberá definir su Acción en :

  ...  

Donde FileCleanerEXE es un binario (en mi caso un pequeño progtwig de c ++ que realiza la acción personalizada) que también se define en :

  ...  

El verdadero truco para esto es la condición de Installed AND NOT UPGRADINGPRODUCTCODE en la Acción personalizada, sin que su acción se ejecute en cada actualización (ya que una actualización es realmente una desinstalación y luego reinstalar). Lo cual si está borrando archivos probablemente no sea lo que quiere durante la actualización.

En una nota al margen: recomiendo pasar por la molestia de usar algo como el progtwig C ++ para hacer la acción, en lugar de un script por lotes debido a la potencia y el control que proporciona, y puedes evitar que la ventana “prompt cmd” destelle mientras tu instalador se ejecuta.

El mayor problema con una secuencia de comandos por lotes es deshacerse de la restauración cuando el usuario hace clic en cancelar (o algo va mal durante la instalación). La forma correcta de manejar este escenario es crear una CustomAction que agregue filas temporales a la tabla RemoveFiles. De esa forma, Windows Installer maneja los casos de reversión por usted. Es increíblemente más simple cuando ves la solución.

De todos modos, para que una acción solo se ejecute durante la desinstalación, agrega un elemento Condición con:

 REMOVE ~= "ALL" 

el ~ = dice comparar mayúsculas y minúsculas (aunque creo que ALL siempre es uppercaesd). Consulte la documentación de MSI SDK sobre Sintaxis de condiciones para obtener más información.

PD: Nunca ha habido un caso en el que me senté y pensé: “Oh, el archivo por lotes sería una buena solución en un paquete de instalación”. En realidad, encontrar un paquete de instalación que tenga un archivo por lotes solo me animará a devolver el producto para obtener un reembolso.

Utilicé Custom Action codificada por separado en C ++ DLL y usé la DLL para llamar a la función apropiada en Desinstalar usando esta syntax:

  

Usando el bloque de código anterior, pude ejecutar cualquier función definida en C ++ DLL en la desinstalación. FYI, mi función de desinstalación tenía un código relacionado con la eliminación de los datos de usuario actuales y las entradas de registro.

Aquí hay un conjunto de propiedades que hice que se sienten más intuitivas de usar que las cosas integradas. Las condiciones se basan en la tabla de verdad proporcionada por ahmd0.

  < ![CDATA[Installed="" AND REINSTALL="" AND UPGRADINGPRODUCTCODE="" AND REMOVE=""]]> < ![CDATA[Installed<>"" AND REINSTALL="" AND UPGRADINGPRODUCTCODE="" AND REMOVE="ALL"]]> < ![CDATA[Installed<>"" AND REINSTALL="" AND UPGRADINGPRODUCTCODE="" AND REMOVE=""]]> < ![CDATA[Installed<>"" AND REINSTALL="ALL" AND UPGRADINGPRODUCTCODE="" AND REMOVE=""]]> < ![CDATA[Installed<>"" AND REINSTALL="" AND UPGRADINGPRODUCTCODE<>"" AND REMOVE="ALL"]]> 

Aquí hay un poco de uso de muestra:

  NOT _UNINSTALL _INSTALL OR _UPGRADE _UNINSTALL OR _UPGRADE NOT _UNINSTALL NOT _UNINSTALL 

Cuestiones: