Removendo arquivos ao desinstalar o WiX
-
10-07-2019 - |
Pergunta
Ao desinstalar o meu pedido, eu gostaria de configurar a configuração Wix para remover todo o arquivos que foram adicionados após a instalação original . Parece que os remove desinstalação apenas os diretórios e arquivos que foram originalmente instaladas a partir do arquivo MSI e deixa tudo o mais que foi adicionado mais tarde na pasta do aplicativo. Em outras palavras, eu gostaria de limpar o diretório ao desinstalar. Como posso fazer isso?
Solução
Use RemoveFile elemento com On = " desinstalação ". Aqui está um exemplo:
<Directory Id="CommonAppDataFolder" Name="CommonAppDataFolder">
<Directory Id="MyAppFolder" Name="My">
<Component Id="MyAppFolder" Guid="*">
<CreateFolder />
<RemoveFile Id="PurgeAppFolder" Name="*.*" On="uninstall" />
</Component>
</Directory>
</Directory>
Atualizar
Não funcionou 100%. Ele removeu os arquivos, no entanto, nenhum dos diretórios adicionais - os criados após a instalação - foram removidos. Quaisquer pensamentos sobre isso? - pribeiro
Infelizmente Windows Installer não suporta exclusão de diretórios com subdiretórios. Neste caso, você tem que recorrer a ação personalizada. Ou, se você sabe o que subpastas são, criar um grupo de elementos RemoveFolder e RemoveFile.
Outras dicas
Use RemoveFolderEx
elemento de extensão Util em WiX.
Com esta abordagem, todas as subdirectórios também são removidas (em oposição a usando elemento RemoveFile
directamente ). Este elemento adiciona linhas temporárias para RemoveFile
e mesa RemoveFolder
no banco de dados MSI.
Para fazer isso, eu simplesmente criou uma ação personalizada para ser chamado na desinstalação.
O código de WiX será parecido com este:
<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>
O código para o método OnBeforeUninstall em InstallerCustomActions.DLL será parecido com este (em 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
Aqui está uma variação na sugestão de @ tronda. Estou apagar um ficheiro "install.log" que é criada por outra ação personalizada, durante a desinstalação:
<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>
Tanto quanto eu entendo, eu não posso usar "RemoveFile" porque este arquivo é criado após a instalação, e não faz parte de um grupo de componentes.
Não um especialista WIX, mas uma solução possível (simples?) Para este poderia ser para executar a Execução Calmo ação personalizada que faz parte da construído em extensões de WIX?
Pode executar o href="http://www.computerhope.com/rmdirhlp.htm" rel="noreferrer"> rmdir comando
E a ação personalizada fazendo o trabalho é simples:
Em seguida, você terá que modificar o InstallExecuteSequence conforme documentado muitos lugares. Update:
Teve problemas com esta abordagem. Acabou fazendo uma tarefa personalizada em vez disso, mas ainda considera esta uma solução viável, mas sem obter os detalhes para o trabalho. <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" />
Esta seria uma resposta mais completa para @Pavel sugestão, para mim ele está funcionando 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, sob elemento produto:
<Feature Id="Uninstall">
<ComponentRef Id="UninstallFolder" Primary="yes"/>
</Feature>
Esta abordagem definir um valor de registro com o caminho desejado da pasta a ser excluída na desinstalação. No final, ambos installFolder e pasta de registo são removidos do sistema. Note-se que o caminho para o registro pode ser em outros locais colmeia e outros.