卸载 WiX 时删除文件

问题描述 投票:0回答:6

卸载我的应用程序时,我想配置 Wix 设置以删除原始安装后添加的所有文件。卸载程序似乎只删除了最初从 MSI 文件安装的目录和文件,并保留了后来在应用程序文件夹中添加的所有其他内容。换句话说,我想在卸载时清除该目录。我该怎么做?

wix installation windows-installer custom-action
6个回答
90
投票

使用 RemoveFile 元素 和 On="uninstall"。这是一个例子:

<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 Installer不支持删除带有子目录的目录。在这种情况下,您必须诉诸自定义操作。或者,如果您知道子文件夹是什么,请创建一堆RemoveFolder和RemoveFile元素。


35
投票

使用 WiX 中 Util 扩展中的

RemoveFolderEx
元素。
通过这种方法,所有子目录也会被删除(而不是直接使用 RemoveFile
 元素
)。此元素将临时行添加到 MSI 数据库中的
RemoveFile
RemoveFolder
 表。


13
投票
这是@tronda 建议的一个变体。我正在删除卸载期间由另一个自定义操作创建的文件“install.log”:

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

据我了解,我无法使用“RemoveFile”,因为该文件是在安装后创建的,并且不属于组件组。


13
投票
为此,我只是创建了一个在卸载时调用的自定义操作。

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

InstallerCustomActions.DLL 中 OnBeforeUninstall 方法的代码将如下所示(在 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
    

8
投票
这将是对

@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 和注册表文件夹都将从系统中删除。请注意,注册表的路径可以位于其他配置单元和其他位置。


6
投票
不是 WIX 专家,但可能(更简单?)的解决方案是运行

Quiet Execution Custom Action,它是 WIX 内置扩展的一部分?

可以使用 /S 和 /Q 选项运行

rmdir MS DOS 命令。

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

更新: 对这种方法有问题。最终制作了一个自定义任务,但仍然认为这是一个可行的解决方案,但没有让细节发挥作用。

© www.soinside.com 2019 - 2024. All rights reserved.