Rimuovere i file durante la disinstallazione di WiX


84

Quando disinstallo la mia applicazione, vorrei configurare la configurazione Wix per rimuovere tutti i file che sono stati aggiunti dopo l'installazione originale . Sembra che il programma di disinstallazione rimuova solo le directory ei file che erano stati originariamente installati dal file MSI e lasci tutto il resto che è stato aggiunto in seguito nella cartella dell'applicazione. In altre parole, vorrei eliminare la directory durante la disinstallazione. Come lo faccio?

Risposte:


83

Usa elemento RemoveFile con On = " uninstall ". Ecco un esempio:

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

Aggiornare

Non ha funzionato al 100%. Ha rimosso i file, tuttavia nessuna delle directory aggiuntive - quelle create dopo l'installazione - è stata rimossa. Qualche idea su questo? - pribeiro

Purtroppo Windows Installer non supporta l'eliminazione di directory con sottodirectory. In questo caso devi ricorrere all'azione personalizzata. Oppure, se sai cosa sono le sottocartelle, crea un gruppo di elementi RemoveFolder e RemoveFile.


1
Grazie Pavel. Tuttavia non ha funzionato al 100%. Ha rimosso i file, tuttavia nessuna delle directory aggiuntive - quelle create dopo l'installazione - è stata rimossa. Qualche idea su questo?
pribeiro

Oh, né i file in quelle directory sono stati eliminati.
pribeiro

Quando manterrai i file (file di configurazione per esempio) in "MyAppFolder" negli aggiornamenti principali, avrai problemi con questo approccio. Tutti i file verranno rimossi da un aggiornamento.
Simon

1
È possibile con il tuo codice creare una directory in MyAppFolder? Quando aggiungo una directory dopo </Component>che una compilazione non è riuscitaFound orphaned Component 'MyAppFolder'.
A.Pissicat

2

30

Usa l' RemoveFolderExelemento dall'estensione Util in WiX.
Con questo approccio, vengono rimosse anche tutte le sottodirectory (invece di utilizzare l' RemoveFileelemento direttamente ). Questo elemento aggiunge righe RemoveFilee RemoveFoldertabelle temporanee nel database MSI.


2
Attenzione: quando si utilizza RemoveFolderEx su = "disinstalla", rimuove anche la cartella su un aggiornamento (Wix 3.9). Stesso comportamento su RemoveFilee RemoveFolder. Se si desidera mantenere i file durante un aggiornamento, non è possibile utilizzare tutti questi approcci.
Simon

@ Simone quale approccio suggeriresti se volessi mantenere i file in aggiornamento?
Bijington

@Bijington: quando si desidera mantenere file specifici nella cartella di installazione durante un aggiornamento, utilizzare un'azione personalizzata che esegue codice personalizzato (ad esempio, HandleSetup.exe scritto in c #). Il codice personalizzato fornisce i file durante l'installazione, mantenendo i file durante l'aggiornamento e rimuove i file durante la disinstallazione.
Simon

@Simon grazie, potrebbero dover guardare in tale approccio, anche se questo è attualmente lavorando: stackoverflow.com/a/21383113/32348
Bijington

13

Per fare ciò, ho semplicemente creato un'azione personalizzata da richiamare alla disinstallazione.

Il codice WiX sarà simile a questo:

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

Il codice per il metodo OnBeforeUninstall in InstallerCustomActions.DLL sarà simile a questo (in 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

11

Ecco una variazione sul suggerimento di @ tronda. Sto eliminando un file "install.log" che viene creato da un'altra azione personalizzata, durante la disinstallazione:

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

Per quanto ne so, non posso usare "RemoveFile" perché questo file viene creato dopo l'installazione e non fa parte di un gruppo di componenti.


4
Ho usato questa soluzione, con alcune modifiche per rimuovere l'intera directory: ExeCommand = "cmd / C RD & quot; [INSTALLFOLDER] & quot; / s / q"
Dennis

@Dennis come eliminare INSTALLFOLDER, su Win 10 viene eliminato ma su Windows Server 2012 non lo fa.
eomeroff

Ottima soluzione. Grazie!
Yurii Komarnytskyi

Ho provato una serie di cose: non si potrebbe pensare che potrebbe essere così difficile rimuovere un singolo file durante la disinstallazione. Questo ha funzionato per me però - grazie!
Lucky Luke

7

Questa sarebbe una risposta più completa per il suggerimento di @Pavel , per me funziona 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>

E, sotto Elemento prodotto:

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

Questo approccio imposta un valore di registro con il percorso desiderato della cartella da eliminare durante la disinstallazione. Alla fine, sia INSTALLFOLDER che la cartella del registro vengono rimosse dal sistema. Si noti che il percorso del registro può essere in altri hive e in altre posizioni.


6

Non sei un esperto di WIX, ma potrebbe una possibile (più semplice?) Soluzione a questo essere eseguire l' azione personalizzata di esecuzione silenziosa che fa parte delle estensioni integrate di WIX?

Potrebbe eseguire il comando rmdir MS DOS con le opzioni / S e / Q.

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

E l'azione personalizzata che fa il lavoro è semplice:

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

Quindi dovrai modificare InstallExecuteSequence come documentato in molti punti.

Aggiornamento: ha avuto problemi con questo approccio. Ho finito per creare un'attività personalizzata, ma la considera ancora una soluzione praticabile, ma senza far funzionare i dettagli.


Mi piace questa opzione esclude il fatto che stai includendo cmd.exe nell'installer. Sicuramente ogni macchina lo avrà, basta usare una DirectorySearch per trovarlo! :)
caveman_dick

4
Non farlo. 1) stai incorporando cmd.exenel tuo programma di installazione. 2) Stai apportando modifiche al sistema durante la generazione dello script 3) Non è disponibile alcuna opzione di rollback 4) Non gestisce correttamente i file bloccati
Nick Whaley

Dubito che sia legale distribuire un file dall'installazione di Windows. Inoltre, non è chiaro se funzionerà sul sistema di destinazione che potrebbe eseguire una versione diversa di Windows.
Paul B.

Nessun file è stato distribuito. Utilizza i file installati sul sistema operativo.
tronda
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.