Usuwanie plików podczas odinstalowywania WiX

Podczas odinstalowywania mojej aplikacji chciałbym skonfigurować konfigurację WIX , aby usunąć wszystkie pliki, które zostały dodane po oryginalnej instalacji . Wygląda na to, że deinstalator usuwa tylko katalogi i pliki, które zostały pierwotnie zainstalowane z pliku MSI i pozostawia wszystko, co zostało dodane później w folderze aplikacji. Innymi słowy, chciałbym wyczyścić katalog podczas odinstalowywania. Jak mam to zrobić?

Author: Stein Åsmul, 2008-10-12

6 answers

Użyj removefile element z On= " uninstall". Oto przykład:

<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

Nie zadziałało w 100%. Usunął pliki, jednak żaden z dodatkowych katalogów - te powstałe po instalacji - zostały usunięte. Jakieś pomysły na ten temat? - pribeiro

Niestety Instalator Windows nie obsługuje usuwania katalogów z podkatalogami. W tym przypadku musisz uciekać się do niestandardowych działań. Lub, jeśli dowiedz się, czym są podfoldery, utwórz kilka elementów RemoveFolder i 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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-24 23:33:06

Użycie RemoveFolderEx element z rozszerzenia Util w WiX.
Dzięki takiemu podejściu wszystkie podkatalogi są również usuwane (w przeciwieństwie do używając elementu RemoveFile bezpośrednio). Ten element dodaje tymczasowe wiersze do tabeli RemoveFile i RemoveFolder w bazie danych 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:09:56

Aby to zrobić, po prostu stworzyłem niestandardową akcję, która zostanie wywołana podczas dezinstalacji.

Kod WiX będzie wyglądał tak:

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

Kod dla metody OnBeforeUninstall w InstallerCustomActions.DLL będzie wyglądał tak (w 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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-12 01:52:20

Oto wariacja na temat sugestii @tronda. Usuwam plik " install.log", który zostanie utworzony przez inną niestandardową akcję podczas odinstalowywania:

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

O ile rozumiem, nie mogę użyć "RemoveFile", ponieważ plik ten jest tworzony po instalacji i nie jest częścią grupy komponentów.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-07 15:37:38

Nie ekspert WIX, ale czy możliwe (prostsze?) rozwiązaniem jest uruchomienie Quiet Execution Custom Action która jest częścią wbudowanych rozszerzeń WIX?

Może uruchomić rmdir MS DOS z opcjami /s i /Q.

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

A niestandardowa akcja wykonująca zadanie jest prosta:

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

Następnie będziesz musiał zmodyfikować InstallExecuteSequence, jak udokumentowano w wielu miejscach.

Aktualizacja: Miał problemy z tym podejściem. / Align = "left" / Tworzenie niestandardowego zadania, ale nadal uważa to za realne rozwiązanie, ale bez wprowadzania szczegółów do pracy.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-04 18:56:05

To byłaby bardziej kompletna odpowiedź dla @Pavel sugestia, dla mnie działa w 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>

Oraz, pod elementem produktu:

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

To podejście ustawia wartość rejestru z żądaną ścieżką folderu, który ma zostać usunięty podczas dezinstalacji. Na końcu zarówno folder INSTALLFOLDER, jak i folder rejestru są usuwane z systemu. Zauważ, że ścieżka do rejestru może znajdować się w innym ulu i innych miejscach.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:50