Supprimer des fichiers lors de la désinstallation de WiX

lors de la désinstallation de mon application, je voudrais configurer le Wix setup pour supprimer tous les fichiers qui ont été ajoutés après l'installation originale . Il semble que le désinstalleur ne supprime que les répertoires et les fichiers qui ont été installés à l'origine à partir du fichier MSI et il laisse tout le reste qui a été ajouté plus tard dans le dossier d'application. En d'autres termes, j'aimerais purger le répertoire lors de la désinstallation. Comment dois-je faire?

72
demandé sur Stein Åsmul 2008-10-12 23:41:29

6 réponses

Utiliser RemoveFile élément avec=" 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

ça n'a pas marché à 100%. Il supprime les fichiers, cependant, aucun des répertoires supplémentaires - ceux créés après l'installation, ont été retirés. Des idées à ce sujet? - pribeiro

Malheureusement Windows Installer ne supporte pas 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 tas D'éléments RemoveFolder et RemoveFile.

76
répondu Pavel Chuchuva 2016-02-24 23:33:06

Utilisation RemoveFolderEx élément d'Util extension dans WiX.

Avec cette approche, tous les sous-répertoires sont également supprimés (par opposition à utilisant RemoveFile élément directement ). Cet élément ajoute des lignes temporaires aux tables RemoveFile et RemoveFolder de la base de données MSI.

27
répondu Alexey Ivanov 2017-05-23 12:09:56

Pour ce faire, j'ai simplement créé une action personnalisée pour être appelé sur désinstaller.

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=&quot;[TARGETDIR]\Bin&quot; &quot;[#InstallerCustomActionsDLL]&quot; &quot;[#InstallerCustomActionsDLLCONFIG]&quot;" />

<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 pour 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
12
répondu Friend Of George 2014-08-12 01:52:20

voici une variante de la suggestion de @tronda. Je supprime un fichier "install".journal" qui est créée par une autre Action Personnalisée, lors de la Désinstallation:

<Product>
    <CustomAction Id="Cleanup_logfile" Directory="INSTALLFOLDER"
    ExeCommand="cmd /C &quot;del install.log&quot;"
    Execute="deferred" Return="ignore" HideTarget="no" Impersonate="no" />

    <InstallExecuteSequence>
      <Custom Action="Cleanup_logfile" Before="RemoveFiles" >
        REMOVE="ALL"
      </Custom>
    </InstallExecuteSequence>
</Product>

autant que je sache, je ne peux pas utiliser" RemoveFile " parce que ce fichier est créé après l'installation, et ne fait pas partie d'un groupe de composants.

8
répondu Pierre 2013-07-07 15:37:38

pas un expert WIX, mais pourrait-il une possible (plus simple? la solution à cela est de lancer le Calme de l'Exécution de l'Action Personnalisée , qui fait partie de la construction dans les extensions 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 faire le travail est simple:

<CustomAction Id="DeleteFolder" BinaryKey="CommandPrompt" 
              ExeCommand='/c rmdir /S /Q "[CommonAppDataFolder]MyAppFolder\PurgeAppFolder"' 
              Execute="immediate" Return="check" />

, Alors vous devrez modifier le InstallExecuteSequence comme documenté de nombreux endroits.

mise à Jour: Eu des problèmes avec cette approche. A fini par faire une tâche sur mesure à la place, mais considère toujours que c'est une solution viable, mais sans obtenir les détails pour travailler.

7
répondu tronda 2011-08-04 18:56:05

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 de produit:

<Feature Id="Uninstall">
    <ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>

cette approche définit une valeur de registre avec le chemin désiré du dossier à supprimer lors de la désinstallation. À la fin, les deux fichiers INSTALLFOLDER et registry sont supprimés du système. Notez que le chemin vers le Registre peut être à d'autres ruches et d'autres endroits.

3
répondu Eli 2017-05-23 11:46:50