Lors de la désinstallation de mon application, je voudrais configurer la configuration Wix pour supprimer tous les fichiers ajoutés après l'installation d'origine . Il semble que le programme de désinstallation supprime uniquement les répertoires et fichiers qui ont été initialement installés à partir du fichier MSI et qu'il laisse tout le reste ajouté plus tard dans le dossier d'application. En d'autres termes, j'aimerais purger le répertoire lors de la désinstallation. Comment je fais ça?
Utilisez élément RemoveFile avec On = " désinstaller ". Voici un exemple:
<Directory Id="CommonAppDataFolder" Name="CommonAppDataFolder">
<Directory Id="MyAppFolder" Name="My">
<Component Id="MyAppFolder" Guid="*">
<CreateFolder />
<RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
</Component>
</Directory>
</Directory>
Mise à jour
Cela n'a pas fonctionné à 100%. Il a supprimé les fichiers, mais aucun des répertoires supplémentaires - ceux créés après l'installation - n'a été supprimé. Des réflexions là-dessus? - pribeiro
Malheureusement, Windows Installer ne prend pas en charge la suppression de répertoires avec des sous-répertoires. Dans ce cas, vous devez recourir à une action personnalisée. Ou, si vous savez ce que sont les sous-dossiers, créez un groupe d'éléments RemoveFolder et RemoveFile.
Utilisez RemoveFolderEx
élément de l'extension Util dans WiX.
Avec cette approche, tous les sous-répertoires sont également supprimés (par opposition à en utilisant directement l'élément RemoveFile
). Cet élément ajoute des lignes temporaires à la table RemoveFile
et RemoveFolder
dans la base de données MSI.
Pour ce faire, j'ai simplement créé une action personnalisée à appeler lors de la désinstallation.
Le code WiX ressemblera à ceci:
<Binary Id="InstallUtil" src="InstallUtilLib.dll" />
<CustomAction Id="DIRCA_TARGETDIR" Return="check" Execute="firstSequence" Property="TARGETDIR" Value="[ProgramFilesFolder][Manufacturer]\[ProductName]" />
<CustomAction Id="Uninstall" BinaryKey="InstallUtil" DllEntry="ManagedInstall" Execute="deferred" />
<CustomAction Id="UninstallSetProp" Property="Uninstall" Value="/installtype=notransaction /action=uninstall /LogFile= /targetDir="[TARGETDIR]\Bin" "[#InstallerCustomActionsDLL]" "[#InstallerCustomActionsDLLCONFIG]"" />
<Directory Id="BinFolder" Name="Bin" >
<Component Id="InstallerCustomActions" Guid="*">
<File Id="InstallerCustomActionsDLL" Name="SetupCA.dll" LongName="InstallerCustomActions.dll" src="InstallerCustomActions.dll" Vital="yes" KeyPath="yes" DiskId="1" Compressed="no" />
<File Id="InstallerCustomActionsDLLCONFIG" Name="SetupCA.con" LongName="InstallerCustomActions.dll.Config" src="InstallerCustomActions.dll.Config" Vital="yes" DiskId="1" />
</Component>
</Directory>
<Feature Id="Complete" Level="1" ConfigurableDirectory="TARGETDIR">
<ComponentRef Id="InstallerCustomActions" />
</Feature>
<InstallExecuteSequence>
<Custom Action="UninstallSetProp" After="MsiUnpublishAssemblies">$InstallerCustomActions=2</Custom>
<Custom Action="Uninstall" After="UninstallSetProp">$InstallerCustomActions=2</Custom>
</InstallExecuteSequence>
Le code de la méthode OnBeforeUninstall dans InstallerCustomActions.DLL ressemblera à ceci (en VB).
Protected Overrides Sub OnBeforeUninstall(ByVal savedState As System.Collections.IDictionary)
MyBase.OnBeforeUninstall(savedState)
Try
Dim CommonAppData As String = Me.Context.Parameters("CommonAppData")
If CommonAppData.StartsWith("\") And Not CommonAppData.StartsWith("\\") Then
CommonAppData = "\" + CommonAppData
End If
Dim targetDir As String = Me.Context.Parameters("targetDir")
If targetDir.StartsWith("\") And Not targetDir.StartsWith("\\") Then
targetDir = "\" + targetDir
End If
DeleteFile("<filename.extension>", targetDir) 'delete from bin directory
DeleteDirectory("*.*", "<DirectoryName>") 'delete any extra directories created by program
Catch
End Try
End Sub
Private Sub DeleteFile(ByVal searchPattern As String, ByVal deleteDir As String)
Try
For Each fileName As String In Directory.GetFiles(deleteDir, searchPattern)
File.Delete(fileName)
Next
Catch
End Try
End Sub
Private Sub DeleteDirectory(ByVal searchPattern As String, ByVal deleteDir As String)
Try
For Each dirName As String In Directory.GetDirectories(deleteDir, searchPattern)
Directory.Delete(dirName)
Next
Catch
End Try
End Sub
Voici une variante de la suggestion de @ tronda. Je supprime un fichier "install.log" qui est créé par une autre action personnalisée, lors de la désinstallation:
<Product>
<CustomAction Id="Cleanup_logfile" Directory="INSTALLFOLDER"
ExeCommand="cmd /C "del install.log""
Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="Cleanup_logfile" Before="RemoveFiles" >
REMOVE="ALL"
</Custom>
</InstallExecuteSequence>
</Product>
Pour autant que je comprends, je ne peux pas utiliser "RemoveFile" car ce fichier est créé après l'installation et ne fait pas partie d'un groupe de composants.
Pas un expert WIX, mais une solution possible (plus simple?) Pourrait être d'exécuter Quiet Execution Custom Action qui fait partie des extensions intégrées de WIX?
Pourrait exécuter la commande rmdir MS DOS avec les options/S et/Q.
<Binary Id="CommandPrompt" SourceFile="C:\Windows\System32\cmd.exe" />
Et l'action personnalisée qui fait le travail est simple:
<CustomAction Id="DeleteFolder" BinaryKey="CommandPrompt"
ExeCommand='/c rmdir /S /Q "[CommonAppDataFolder]MyAppFolder\PurgeAppFolder"'
Execute="immediate" Return="check" />
Ensuite, vous devrez modifier le InstallExecuteSequence comme documenté de nombreux endroits.
Mise à jour: J'ai eu des problèmes avec cette approche. A fini par faire une tâche personnalisée à la place, mais considère toujours que c'est une solution viable, mais sans que les détails fonctionnent.
Ce serait une réponse plus complète pour @ Pavel suggestion, pour moi ça marche à 100%:
<Fragment Id="FolderUninstall">
<?define RegDir="SYSTEM\ControlSet001\services\[Manufacturer]:[ProductName]"?>
<?define RegValueName="InstallDir"?>
<Property Id="INSTALLFOLDER">
<RegistrySearch Root="HKLM" Key="$(var.RegDir)" Type="raw"
Id="APPLICATIONFOLDER_REGSEARCH" Name="$(var.RegValueName)" />
</Property>
<DirectoryRef Id='INSTALLFOLDER'>
<Component Id="UninstallFolder" Guid="*">
<CreateFolder Directory="INSTALLFOLDER"/>
<util:RemoveFolderEx Property="INSTALLFOLDER" On="uninstall"/>
<RemoveFolder Id="INSTALLFOLDER" On="uninstall"/>
<RegistryValue Root="HKLM" Key="$(var.RegDir)" Name="$(var.RegValueName)"
Type="string" Value="[INSTALLFOLDER]" KeyPath="yes"/>
</Component>
</DirectoryRef>
</Fragment>
Et, sous l'élément produit:
<Feature Id="Uninstall">
<ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>
Cette approche définit une valeur de Registre avec le chemin d'accès souhaité du dossier à supprimer lors de la désinstallation. À la fin, INSTALLFOLDER et le dossier de registre sont supprimés du système. Notez que le chemin d'accès au Registre peut être à d'autres Hive et à d'autres emplacements.