2008-11-26 16 views
135

Me gustaría modificar un instalador de MSI (creado a través de WiX) para eliminar un directorio completo en la desinstalación.¿Cómo agregar una acción personalizada de WiX que solo ocurre en la desinstalación (a través de MSI)?

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

me di cuenta de la pregunta similares desbordamiento de pila Removing files when uninstalling WiX, pero me preguntaba si esto se podría hacer más simple uso de una llamada a un script por lotes para eliminar la carpeta.

Esta es la primera vez que uso WiX, y sigo teniendo el truco de custom actions. ¿Cuál sería un ejemplo básico de una acción personalizada que ejecutará un script por lotes en la desinstalación?

Respuesta

45

Puede hacerlo con una acción personalizada. Se puede añadir un refrence a su acción personalizada bajo <InstallExecuteSequence>:

<InstallExecuteSequence> 
... 
    <Custom Action="FileCleaner" After='InstallFinalize'> 
      Installed AND NOT UPGRADINGPRODUCTCODE</Custom> 

Entonces usted también tendrá que definir su acción bajo <Product>:

<Product> 
... 
    <CustomAction Id='FileCleaner' BinaryKey='FileCleanerEXE' 
       ExeCommand='' Return='asyncNoWait' /> 

Dónde FileCleanerEXE es un binario (en mi caso un poco de C++ programa que hace la acción personalizada) que también se define en <Product>:

<Product> 
... 
    <Binary Id="FileCleanerEXE" SourceFile="path\to\fileCleaner.exe" /> 

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

En una nota al margen: Recomiendo pasar por el problema de usar algo como el programa C++ para hacer la acción, en lugar de un script por lotes debido a la potencia y el control que proporciona, y puede evitar el "prompt cmd" la ventana de parpadear mientras se ejecuta su instalador.

+3

25 votos positivos pero no una respuesta aceptada. Bienvenido al mundo de los instaladores! :) –

+3

Esto realmente no funciona. Cuando desee ejecutar un fileCleaner.exe, que está instalado en su propia carpeta de instalación, se tratará de un problema de gallina y huevo: se ejecutará 'CustomAction'" After = 'InstallFinalize' ". En este punto, todos los archivos se eliminan de la carpeta de Instalación. También el fileCleaner.exe. Por lo tanto, no puede ejecutarlo a través de una acción personalizada. Esta respuesta es simplemente incorrecta. ¡Me estoy preguntando sobre los 42 votaciones ascendentes! – Simon

33

El mayor problema con una secuencia de comandos por lotes es manejar la reversió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 tener una acción sólo ejecutar durante la desinstalación añadir un elemento de estado que presenta:

REMOVE ~= "ALL" 

el ~ = dice comparar entre mayúsculas y minúsculas (a pesar de que creo que todos siempre uppercaesd). Vea el MSI SDK documentation about Conditions Syntax para 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.

171

EDIT: Quizás mire la respuesta inmediatamente debajo.


Este tema ha sido un dolor de cabeza durante mucho tiempo. Finalmente lo resolví. Existen algunas soluciones en línea, pero ninguna de ellas funciona realmente. Y, por supuesto, no hay documentación. Así, en la tabla de abajo hay varias propiedades que se sugieren para usar y los valores que ellos tienen para varios escenarios de instalación:

alt text

Así que en mi caso yo quería una CA que se ejecutará sólo en desinstala - no actualizaciones, no reparaciones o modificaciones. De acuerdo con la tabla anterior tuve que usar

<Custom Action='CA_ID' Before='other_CA_ID'> 
     (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom> 

¡Y funcionó!

+23

¿Son correctos los valores en esa tabla? ¿Por qué necesitarías agregar REMOVE = "ALL"? NO ACTUALIZAR CÓDIGO DE PRODUCTO solo es cierto para una desinstalación (de acuerdo con el cuadro), por lo que (NO ACTUALIZAR CÓDIGO DE PRODUCTO) Y (ELIMINAR = "TODO") también sería cierto solo en una desinstalación. El REMOVE = "ALL" parece innecesario. –

+2

Estoy de acuerdo con @ToddRopog: el ejemplo y la tabla de verdad no parecen estar de acuerdo. ¿Es eso realmente correcto? –

+18

La tabla de verdad es un poco incorrecta. NO ACTUALIZAR EL CÓDIGO DE PRODUCTO es cierto para una primera instalación también – Neil

97

Existen varios problemas con yaluna's answer, también los nombres de propiedades son sensibles a mayúsculas y minúsculas, Installed es la ortografía correcta (INSTALLED no funcionará). La tabla anterior debería haber sido la siguiente:

enter image description here

también asumiendo una reparación completa & desinstalar los valores reales de las propiedades podrían ser:

enter image description here

La documentación WiX Expression Syntax dice:

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

Las propiedades están documentados en la Guía del instalador de Windows (por ejemplo Installed)

EDIT: pequeña corrección a la primera tabla; Evidentemente, "Desinstalar" también puede ocurrir con solo REMOVE siendo True.

+2

ELIMINAR también parece estar configurado para Cambiar – szx

+0

La columna 'Actualizar', es que durante la secuencia de desinstalación del la versión anterior o la secuencia de instalación de la nueva versión? –

+0

@NickWhaley: No lo he investigado por un tiempo, pero creo que la opción "Actualizar" es solo cuando instalo una versión más grande que la que ya está instalada. – ahmd0

0

I utilizarse acción personalizada codificada por separado en C++ DLL y se utiliza la DLL para llamar a la función apropiada sobre la desinstalación con esta sintaxis:

<CustomAction Id="Uninstall" BinaryKey="Dll_Name" 
       DllEntry="Function_Name" Execute="deferred" /> 

utilizando el bloque de código anterior, yo era capaz de 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.

Cuestiones relacionadas