Удаление файлов при удалении WiX
-
10-07-2019 - |
Вопрос
При удалении моего приложения я хотел бы настроить Викс настройка для удаления всех добавленных файлов после оригинальной установки.Такое ощущение, что деинсталлятор удаляет из MSI-файла только те каталоги и файлы, которые были изначально установлены, а все остальное, что было добавлено позже, оставляет в папке приложения.Другими словами, я хотел бы очистить каталог при удалении.Как мне это сделать?
Решение
Использовать Элемент RemoveFile с Вкл.="удалить".Вот пример:
<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%.Он удалил файлы, однако ни один из дополнительных каталогов - те, которые созданы после установки - не были удалены.Есть мысли по этому поводу?- прибейро
К сожалению, установщик 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>
И, под элементом Product:
<Feature Id="Uninstall">
<ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>
Этот подход устанавливает значение реестра с указанием желаемого пути к папке, которая будет удалена при удалении. В конце и INSTALLFOLDER, и папка реестра удаляются из системы. Обратите внимание, что путь к реестру может быть в другом улье и других местах.