Je souhaite modifier un programme d’installation MSI (créé via WiX ) afin de supprimer un répertoire entier lors de la désinstallation.
Je comprends les options RemoveFile
et RemoveFolder
de WiX, mais elles ne sont pas assez robustes pour supprimer de manière récursive tout un dossier dont le contenu a été créé après l'installation.
J'ai remarqué la même question de Stack Overflow Suppression de fichiers lors de la désinstallation de WiX, mais je me demandais si cela pourrait être fait plus simplement à l'aide de un appel à un script batch pour supprimer le dossier.
C'est la première fois que j'utilise WiX et je comprends toujours actions personnalisées . Quel serait un exemple de base d'une action personnalisée qui exécutera un script de traitement par lots lors de la désinstallation?
EDIT : Regardez peut-être la réponse ci-dessous.
Ce sujet est un casse-tête depuis longtemps. J'ai finalement compris. Il existe des solutions en ligne, mais aucune d’entre elles ne fonctionne vraiment. Et bien sûr, il n'y a pas de documentation. Ainsi, dans le tableau ci-dessous, il est suggéré d'utiliser plusieurs propriétés et les valeurs qu'elles ont pour différents scénarios d'installation:
Donc, dans mon cas, je voulais une autorité de certification qui ne s’exécutera qu’à la désinstallation, pas aux mises à niveau, ni aux réparations ni aux modifications. Selon le tableau ci-dessus, je devais utiliser
<Custom Action='CA_ID' Before='other_CA_ID'>
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
Et ça a marché!
Il y a plusieurs problèmes avec réponse de yaluna , les noms de propriétés sont sensibles à la casse, Installed
est l'orthographe correcte (INSTALLED
ne fonctionnera pas). Le tableau ci-dessus aurait dû être ceci:
En supposant également une réparation complète et la désinstallation, les valeurs réelles des propriétés pourraient être:
La documentation syntaxe de WiX Expression indique:
Dans ces expressions, vous pouvez utiliser des noms de propriété (rappelez-vous qu'ils sont sensibles à la casse).
Les propriétés sont décrites dans le Windows Installer Guide (par exemple, Installé ).
EDIT: petite correction à la première table; évidemment, "Uninstall" peut aussi arriver avec juste REMOVE
être True
.
Vous pouvez le faire avec une action personnalisée. Vous pouvez ajouter une référence à votre action personnalisée sous <InstallExecuteSequence>
:
<InstallExecuteSequence>
...
<Custom Action="FileCleaner" After='InstallFinalize'>
Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
Ensuite, vous devrez également définir votre action sous <Product>
:
<Product>
...
<CustomAction Id='FileCleaner' BinaryKey='FileCleanerEXE'
ExeCommand='' Return='asyncNoWait' />
Où FileCleanerEXE est un binaire (dans mon cas un petit programme c ++ qui effectue l'action personnalisée) qui est également défini sous <Product>
:
<Product>
...
<Binary Id="FileCleanerEXE" SourceFile="path\to\fileCleaner.exe" />
Le vrai truc à cela est le Installed AND NOT UPGRADINGPRODUCTCODE
_ condition sur l’action personnalisée, sans que votre action soit exécutée à chaque mise à niveau (puisqu’une mise à niveau est réellement une désinstallation puis une réinstallation). Ce qui, si vous supprimez des fichiers, n’est probablement pas ce que vous souhaitez lors de la mise à niveau.
Remarque: je vous recommande de ne pas utiliser un programme similaire au programme C++ pour effectuer l'action, mais d'utiliser un script batch en raison de la puissance et du contrôle qu'il fournit - et vous pouvez empêcher la fenêtre "Invite cmd" de clignoter pendant que votre installateur s'exécute.
Le principal problème d'un script batch est la gestion de la restauration lorsque l'utilisateur clique sur Annuler (ou en cas de problème lors de l'installation). La bonne façon de gérer ce scénario consiste à créer un CustomAction qui ajoute des lignes temporaires à la table RemoveFiles. De cette façon, Windows Installer gère les cas de restauration pour vous. C'est incroyablement simple quand on voit la solution.
Quoi qu'il en soit, pour qu'une action ne soit exécutée que pendant la désinstallation, ajoutez un élément Condition avec:
REMOVE ~= "ALL"
le ~ = dit que la comparaison est insensible à la casse (même si je pense que ALL est toujours en majuscule). Reportez-vous à la documentation de MSI SDK sur la syntaxe des conditions pour plus d'informations.
PS: Il n'y a jamais eu de cas où je me suis assis et que je pensais: "Oh, un fichier batch serait une bonne solution dans un package d'installation." En fait, trouver un package d'installation contenant un fichier de commandes m'encouragerait uniquement à renvoyer le produit pour un remboursement.
Voici un ensemble de propriétés que j'ai créées et qui sont plus intuitives à utiliser que les fonctions intégrées. Les conditions sont basées sur la table de vérité fournie ci-dessus par ahmd0.
<!-- truth table for installer varables (install vs uninstall vs repair vs upgrade) https://stackoverflow.com/a/17608049/1721136 -->
<SetProperty Id="_INSTALL" After="FindRelatedProducts" Value="1"><![CDATA[Installed="" AND PREVIOUSVERSIONSINSTALLED=""]]></SetProperty>
<SetProperty Id="_UNINSTALL" After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED="" AND REMOVE="ALL"]]></SetProperty>
<SetProperty Id="_CHANGE" After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL="" AND PREVIOUSVERSIONSINSTALLED<>"" AND REMOVE=""]]></SetProperty>
<SetProperty Id="_REPAIR" After="FindRelatedProducts" Value="1"><![CDATA[REINSTALL<>""]]></SetProperty>
<SetProperty Id="_UPGRADE" After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED<>"" ]]></SetProperty>
Voici quelques exemples d'utilisation:
<Custom Action="CaptureExistingLocalSettingsValues" After="InstallInitialize">NOT _UNINSTALL</Custom>
<Custom Action="GetConfigXmlToPersistFromCmdLineArgs" After="InstallInitialize">_INSTALL OR _UPGRADE</Custom>
<Custom Action="ForgetProperties" Before="InstallFinalize">_UNINSTALL OR _UPGRADE</Custom>
<Custom Action="SetInstallCustomConfigSettingsArgs" Before="InstallCustomConfigSettings">NOT _UNINSTALL</Custom>
<Custom Action="InstallCustomConfigSettings" Before="InstallFinalize">NOT _UNINSTALL</Custom>
Problèmes:
J'ai utilisé Custom Action séparément codé en C++ DLL et ai utilisé le DLL pour appeler la fonction appropriée lors de la désinstallation à l'aide de cette syntaxe:
<CustomAction Id="Uninstall" BinaryKey="Dll_Name"
DllEntry="Function_Name" Execute="deferred" />
En utilisant le bloc de code ci-dessus, j'ai été en mesure d'exécuter n'importe quelle fonction définie dans C++ DLL lors de la désinstallation. FYI, ma fonction de désinstallation comportait du code relatif à la suppression des données utilisateur actuelles et des entrées de registre.