Comment ajouter une action personnalisée WiX qui ne se produit que lors de la désinstallation (via MSI)?

je voudrais modifier un installateur MSI (créé par WiX ) pour supprimer un répertoire entier lors de la désinstallation.

je comprends les options RemoveFile et RemoveFolder dans WiX, mais celles-ci ne sont pas assez robustes pour supprimer récursivement un dossier entier qui a du contenu créé après l'installation.

j'ai remarqué la question similaire sur le débordement de la pile Supprimer des fichiers lors de la désinstallation de WiX , mais je me demandais si cela pouvait être fait plus simplement en utilisant un appel à un script de lot pour supprimer le dossier.

c'est la première fois que J'utilise WiX, et j'ai encore le coup de main avec actions personnalisées . Quel serait un exemple de base d'une action personnalisée qui lancera un script batch sur uninstall?

141
demandé sur Community 2008-11-26 17:41:52

6 réponses

EDIT : peut-être regarder la réponse immédiatement ci-dessous.


ce sujet est un casse-tête depuis longtemps. J'ai enfin compris. Il y a des solutions en ligne, mais aucune ne fonctionne vraiment. Et bien sûr, il n'y a pas de documentation. Ainsi, dans le graphique ci-dessous, il y a plusieurs propriétés qui sont suggérées à utiliser et les valeurs qu'elles ont pour divers scénarios d'installation:

alt text

donc dans mon cas je voulais un CA qui ne fonctionnera que sur les désinstallations - pas les mises à niveau, pas les réparations ou les modifications. Selon le tableau ci-dessus, j'ai dû utiliser

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

et ça a marché!

179
répondu Stein Åsmul 2017-12-18 21:52:26

il y a plusieurs problèmes avec la réponse de yaluna , aussi les noms de propriété sont sensibles à la casse, Installed est l'orthographe correcte ( INSTALLED ne fonctionnera pas). Le tableau ci-dessus aurait dû être le suivant:

enter image description here

également en supposant une réparation complète et uninstall les valeurs réelles des propriétés pourraient être:

enter image description here

le WiX la Syntaxe de l'Expression documentation dit:

dans ces expressions, vous pouvez utiliser des noms de propriétés (rappelez-vous qu'ils sont sensibles à la casse).

les propriétés sont documentées dans le guide D'installation de Windows (par exemple installé )

EDIT: petite correction à la première table; évidemment "Uninstall" peut également se produire avec juste REMOVE étant True .

112
répondu ahmd0 2017-06-06 14:21:20

Vous pouvez le faire avec une action personnalisée. Vous pouvez ajouter un renvoi à votre action sur mesure sous <InstallExecuteSequence> :

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

alors vous devrez aussi 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 fait l'action personnalisée) qui est également défini sous <Product> :

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

le vrai truc est le Installed AND NOT UPGRADINGPRODUCTCODE condition sur L'Action personnalisée, sans que votre action sera lancée sur chaque mise à niveau (depuis une mise à niveau est vraiment une désinstallation puis réinstaller). Ce qui, si vous supprimez des fichiers, n'est probablement pas ce que vous voulez pendant la mise à jour.

Sur une note de côté: je recommande de passer par la difficulté de l'utilisation de quelque chose comme un programme C++ pour effectuer l'action, au lieu d'un script de commandes en raison de la puissance et le contrôle qu'elle fournit, et vous pouvez éviter le "invite de cmd" fenêtre de clignoter alors que votre installateur fonctionne.

46
répondu csexton 2014-08-07 18:42:54

le plus gros problème avec un script batch est de gérer le rollback lorsque l'utilisateur clique sur cancel (ou que quelque chose tourne mal pendant votre installation). La bonne façon de gérer ce scénario est de créer une CustomAction qui ajoute des lignes temporaires à la table RemoveFiles. De cette façon, L'installateur Windows s'occupe des cas de rollback pour vous. Il est incroyablement plus simple quand vous voyez la solution.

quoi qu'il en soit, pour qu'une action ne soit exécutée que pendant la désinstallation, ajouter un élément de Condition avec:

REMOVE ~= "ALL"

le ~= dit comparer cas insensible (même si je pense que tout est toujours uppercaesd). Voir la documentation 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 ai pensé, "Oh, le fichier batch serait une bonne solution dans un paquet d'installation."En fait, trouver un paquet d'installation qui contient un fichier batch ne ferait que m'encourager à retourner le produit pour un remboursement.

35
répondu Rob Mensching 2013-11-21 18:14:39

voici un ensemble de propriétés que j'ai fait qui se sentent plus intuitif à utiliser que la substance intégrée. 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 REINSTALL=""    AND UPGRADINGPRODUCTCODE=""  AND REMOVE=""]]></SetProperty>
<SetProperty Id="_UNINSTALL" After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL=""    AND UPGRADINGPRODUCTCODE=""  AND REMOVE="ALL"]]></SetProperty>
<SetProperty Id="_CHANGE"    After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL=""    AND UPGRADINGPRODUCTCODE=""  AND REMOVE=""]]></SetProperty>
<SetProperty Id="_REPAIR"    After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL="ALL" AND UPGRADINGPRODUCTCODE=""  AND REMOVE=""]]></SetProperty>
<SetProperty Id="_UPGRADE"   After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL=""    AND UPGRADINGPRODUCTCODE<>"" AND REMOVE="ALL"]]></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>

:

1
répondu Bill Tarbell 2018-07-11 04:47:06

j'ai utilisé L'action personnalisée séparément codée en C++ DLL et j'ai utilisé la DLL pour appeler la fonction appropriée lors de la désinstallation en utilisant cette syntaxe:

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

en utilisant le bloc de code ci-dessus, j'ai pu exécuter n'importe quelle fonction définie dans C++ DLL lors de la désinstallation. Pour information, ma fonction de désinstallation avait le code concernant le nettoyage des données utilisateur actuelles et les entrées de registre.

0
répondu Sid 2014-08-07 18:41:24