如何添加仅在卸载时(通过MSI)发生的WiX自定义操作?

时间:2008-11-26 14:41:52

标签: wix windows-installer custom-action

我想修改MSI安装程序(通过WiX创建)以在卸载时删除整个目录。

我理解WiX中的RemoveFileRemoveFolder选项,但这些选项不够强大,无法递归删除包含安装后创建内容的整个文件夹。

我注意到类似的Stack Overflow问题 Removing files when uninstalling WiX ,但我想知道是否可以通过调用批处理脚本删除文件夹来更简单地完成此操作。

这是我第一次使用WiX,而我仍然对custom actions感到兴奋。在卸载时运行批处理脚本的自定义操作的基本示例是什么?

6 个答案:

答案 0 :(得分:181)

编辑:或许请看下面的答案。


这个话题长期以来一直令人头疼。我终于弄明白了。 网上有一些解决方案,但它们都不起作用。当然没有文件。 因此,在下面的图表中,建议使用几个属性以及它们对各种安装方案的值:

alt text

所以在我的情况下,我想要一个仅在卸载时运行的CA--而不是升级,而不是修复或修改。根据上表我不得不使用

<Custom Action='CA_ID' Before='other_CA_ID'>
        (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>

它有效!

答案 1 :(得分:119)

yaluna's answer存在多个问题,属性名称也区分大小写,Installed拼写正确(INSTALLED不起作用)。  上面的表应该是这样的:

enter image description here

同时假设完全修复&amp;卸载属性的实际值可能是:

enter image description here

WiX Expression Syntax文档说:

  

在这些表达式中,您可以使用属性名称(请记住它们区分大小写)。

Windows Installer指南(例如Installed

中记录了这些属性

编辑:对第一张表进行小幅修正;显然,只有REMOVETrue,才会发生“卸载”。

答案 2 :(得分:47)

您可以使用自定义操作执行此操作。您可以在<InstallExecuteSequence>下的自定义操作中添加引用:

<InstallExecuteSequence>
...
  <Custom Action="FileCleaner" After='InstallFinalize'>
          Installed AND NOT UPGRADINGPRODUCTCODE</Custom>

然后您还必须在<Product>

下定义您的操作
<Product> 
...
  <CustomAction Id='FileCleaner' BinaryKey='FileCleanerEXE' 
                ExeCommand='' Return='asyncNoWait'  />

其中FileCleanerEXE是二进制文件(在我的例子中是一个执行自定义操作的小c ++程序),它也在<Product>下定义:

<Product> 
...
  <Binary Id="FileCleanerEXE" SourceFile="path\to\fileCleaner.exe" />

真正的诀窍是自定义操作上的Installed AND NOT UPGRADINGPRODUCTCODE条件,而且每次升级都会运行您的操作(因为升级实际上是卸载然后重新安装)。如果您要删除文件,那么在升级过程中可能不希望这样。

旁注:我建议使用C ++程序之类的东西来执行操作,而不是批处理脚本,因为它提供了电源和控制 - 你可以阻止“cmd提示符”窗口在安装程序运行时闪烁。

答案 3 :(得分:39)

批处理脚本的最大问题是在用户单击取消时处理回滚(或在安装期间出现问题)。处理此方案的正确方法是创建一个CustomAction,将临时行添加到RemoveFiles表。这样Windows Installer就可以为您处理回滚情况。当你看到解决方案时,这简直太简单了。

无论如何,要在卸载期间执行操作,请添加一个Condition元素:

REMOVE ~= "ALL"
<=>〜=表示比较不区分大小写(即使我认为ALL总是上限)。有关详细信息,请参阅MSI SDK documentation about Conditions Syntax

PS:从来没有一个案例我坐下来想,“哦,批处理文件在安装包中是一个很好的解决方案。”实际上,找到一个包含批处理文件的安装包只会鼓励我退回产品以获得退款。

答案 4 :(得分:4)

这是我制作的一组属性,使用起来比内置的东西更直观。条件基于ahmd0上面提供的真值表。

<!-- truth table for installer varables (install vs uninstall vs repair vs upgrade) https://stackoverflow.com/a/17608049/1721136 -->
 <SetProperty Id="_INSTALL"   After="FindRelatedProducts" Value="1"><![CDATA[Installed="" AND PREVIOUSVERSIONSINSTALLED=""]]></SetProperty>
 <SetProperty Id="_UNINSTALL" After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED="" AND REMOVE="ALL"]]></SetProperty>
 <SetProperty Id="_CHANGE"    After="FindRelatedProducts" Value="1"><![CDATA[Installed<>"" AND REINSTALL="" AND PREVIOUSVERSIONSINSTALLED<>"" AND REMOVE=""]]></SetProperty>
 <SetProperty Id="_REPAIR"    After="FindRelatedProducts" Value="1"><![CDATA[REINSTALL<>""]]></SetProperty>
 <SetProperty Id="_UPGRADE"   After="FindRelatedProducts" Value="1"><![CDATA[PREVIOUSVERSIONSINSTALLED<>"" ]]></SetProperty>

以下是一些示例用法:

  <Custom Action="CaptureExistingLocalSettingsValues" After="InstallInitialize">NOT _UNINSTALL</Custom>
  <Custom Action="GetConfigXmlToPersistFromCmdLineArgs" After="InstallInitialize">_INSTALL OR _UPGRADE</Custom>
  <Custom Action="ForgetProperties" Before="InstallFinalize">_UNINSTALL OR _UPGRADE</Custom>
  <Custom Action="SetInstallCustomConfigSettingsArgs" Before="InstallCustomConfigSettings">NOT _UNINSTALL</Custom>
  <Custom Action="InstallCustomConfigSettings" Before="InstallFinalize">NOT _UNINSTALL</Custom>

问题:

答案 5 :(得分:0)

我使用了在C ++ DLL中单独编码的自定义操作,并使用DLL在使用以下语法卸载时调用适当的函数:

<CustomAction Id="Uninstall" BinaryKey="Dll_Name" 
              DllEntry="Function_Name" Execute="deferred" />

使用上面的代码块,我能够在卸载时运行C ++ DLL中定义的任何函数。 仅供参考,我的卸载功能有关于清除当前用户数据和注册表项的代码。