Удаление файлов при удалении WiX
при удалении моего приложения я хотел бы настроить Wix setup для удаления всех файлов, которые были добавлены после первоначальной установки. Похоже, что деинсталлятор удаляет только каталоги и файлы, которые были первоначально установлены из файла MSI, и оставляет все остальное, что было добавлено позже в папке приложения. Другими словами, Я хотел бы очистить каталог при удалении. Как мне это сделать?
6 ответов
использовать элемент RemoveFile С On="удалить". Вот пример:
<Directory Id="CommonAppDataFolder" Name="CommonAppDataFolder">
<Directory Id="MyAppFolder" Name="My">
<Component Id="MyAppFolder" Guid="*">
<CreateFolder />
<RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
</Component>
</Directory>
</Directory>
обновление
это не сработало на 100%. Он удалил файлы, однако ни один из дополнительных каталогов - созданные после установки-были удалены. Есть мысли по этому поводу? – pribeiro
к сожалению, установщик Windows не поддерживает удаление каталогов с подкаталогами. В этом деле вы должны прибегнуть к пользовательским действиям. Или, если вы знаете, что такое вложенные папки, создайте кучу элементов RemoveFolder и RemoveFile.
использовать RemoveFolderEx
элемент из расширения Util в WiX.
При таком подходе все подкаталоги также удаляются (в отличие от используя RemoveFile
элемент). Этот элемент добавляет временные строки RemoveFile
и RemoveFolder
таблица в базе данных MSI.
для этого я просто создал пользовательское действие, которое будет вызываться при удалении.
код WiX будет выглядеть следующим образом:
<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>
код для метода OnBeforeUninstall в InstallerCustomActions.DLL будет выглядеть так (в 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
вот вариант предложения @tronda. Я удаляю файл " install.log", который создается другим пользовательским действием во время удаления:
<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>
насколько я понимаю, я не могу использовать "RemoveFile", потому что этот файл создается после установки, а не частью группы.
не эксперт WIX, но может ли возможный (проще?) решение этой проблемы-запустить Тихое Выполнение Пользовательского Действия что является частью встроенных расширений WIX?
запустить rmdir команда MS DOS с параметрами /S и /Q.
<Binary Id="CommandPrompt" SourceFile="C:\Windows\System32\cmd.exe" />
и пользовательских действий делает работу простой:
<CustomAction Id="DeleteFolder" BinaryKey="CommandPrompt"
ExeCommand='/c rmdir /S /Q "[CommonAppDataFolder]MyAppFolder\PurgeAppFolder"'
Execute="immediate" Return="check" />
тогда вам придется изменить InstallExecuteSequence, как задокументировано многие места.
обновление: Были проблемы с этим подходом. Вместо этого он сделал пользовательскую задачу, но по-прежнему считает это жизнеспособным решением, но без получения деталей для работы.
Это был бы более полный ответ для @Pavel предложение, для меня оно работает 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>
и, под элементом продукта:
<Feature Id="Uninstall">
<ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>
этот подход устанавливает значение реестра с желаемым путем к папке, которая будет удалена при удалении. В конце как INSTALLFOLDER, так и папка реестра удаляются из системы. Обратите внимание, что путь к реестру может находиться в другом улье и других местах.