Eliminación de archivos al desinstalar WiX


Al desinstalar mi aplicación, me gustaría configurar la configuración de Wix para eliminar todos los archivos que se agregaron después de la instalación original. Parece que el desinstalador elimina solo los directorios y archivos que se instalaron originalmente desde el archivo MSI y deja todo lo demás que se agregó más tarde en la carpeta de la aplicación. En otras palabras, me gustaría purgar el directorio al desinstalar. ¿Cómo hago eso?

Author: Stein Åsmul, 2008-10-12

6 answers

Use RemoveFile elementcon On=" uninstall". Aquí hay un ejemplo:

<Directory Id="CommonAppDataFolder" Name="CommonAppDataFolder">
  <Directory Id="MyAppFolder" Name="My">
    <Component Id="MyAppFolder" Guid="*">
      <CreateFolder />
      <RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
    </Component>
  </Directory>
</Directory>

Update

No funcionó al 100%. Eliminó los archivos, sin embargo ninguno de los directorios adicionales - los creados después de la instalación - fueron eliminados. ¿Alguna idea al respecto? - pribeiro

Desafortunadamente Windows Installer no admite la eliminación de directorios con subdirectorios. En este caso tienes que recurrir a la acción personalizada. O, si sepa qué son las subcarpetas, cree un montón de elementos RemoveFolder y RemoveFile.

 76
Author: Pavel Chuchuva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-24 23:33:06

Uso RemoveFolderEx elemento de la extensión Util en WiX.
Con este enfoque, todos los subdirectorios también se eliminan (a diferencia de usando RemoveFile elemento directamente). Este elemento agrega filas temporales a la tabla RemoveFile y RemoveFolder en la base de datos MSI.

 27
Author: Alexey Ivanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:56

Para hacer esto, simplemente creé una acción personalizada para ser llamada al desinstalar.

El código WiX se verá así:

<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>

El código para el método OnBeforeUninstall en InstallerCustomActions.DLL se verá así (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
Author: Friend Of George,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-12 01:52:20

Aquí hay una variación de la sugerencia de @tronda. Estoy borrando un archivo " instalar.registro " que se crea por otra Acción personalizada, durante la desinstalación:

<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>

Por lo que entiendo, no puedo usar "RemoveFile" porque este archivo se crea después de la instalación, y no es parte de un Grupo de Componentes.

 8
Author: Pierre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-07 15:37:38

No es un experto en WIX, pero podría un posible (más simple?) la solución a esto es ejecutar la Acción Personalizada de Ejecución Silenciosa que es parte de las extensiones integradas de WIX?

Podría ejecutar el comando rmdir MS DOS con las opciones /S y /Q.

<Binary Id="CommandPrompt" SourceFile="C:\Windows\System32\cmd.exe" />

Y la acción personalizada que hace el trabajo es simple:

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

Entonces usted tendrá que modificar el InstallExecuteSequence como documentado muchos lugares.

Actualización: Tenía problemas con este enfoque. Terminar hacer una tarea personalizada en su lugar, pero todavía considera esto una solución viable, pero sin conseguir que los detalles funcionen.

 7
Author: tronda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-04 18:56:05

Esta sería una respuesta más completa para@Pavel sugerencia, para mí está funcionando al 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>

Y, en el elemento Producto:

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

Este enfoque establece un valor de registro con la ruta deseada de la carpeta que se eliminará al desinstalar. Al final, tanto INSTALLFOLDER como registry folder se eliminan del sistema. Tenga en cuenta que la ruta al registro puede estar en otras colmenas y otras ubicaciones.

 3
Author: Eli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:50