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

154 windows-installer custom-action wix

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

我理解WiX中的选项RemoveFileRemoveFolder选项,但是它们不够强大,无法递归删除安装后创建内容的整个文件夹.

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

这是我第一次使用WiX,而且我仍然掌握了自定义操作.在卸载时运行批处理脚本的自定义操作的基本示例是什么?

小智 185

编辑:也许看下面的答案.


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

替代文字

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

<Custom Action='CA_ID' Before='other_CA_ID'>
        (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
Run Code Online (Sandbox Code Playgroud)

它奏效了!

  • 该图表中的值是否正确?为什么需要添加REMOVE ="ALL"?NOT UPGRADINGPRODUCTCODE仅适用于卸载(根据图表),因此(NOT UPGRADINGPRODUCTCODE)和(REMOVE ="ALL")也只适用于卸载.REMOVE ="ALL"似乎没必要. (24认同)
  • 真值表略有错误.NOT UPGRADINGPRODUCTCODE也适用于首次安装 (19认同)
  • 我同意@ToddRopog - 示例和真值表似乎不同意.这是真的正确吗? (2认同)
  • 常见条件:http://alekdavis.blogspot.ru/2013/05/wix-woes-what-is-your-installer-doing.html (2认同)
  • 1. 某些表值错误,例如“未升级产品代码/安装”。2. INSTALLED 不存在,该属性称为“Installed”(区分大小写)。3. 没有文档的说法是错误的:相关WiX位于https://www.firegiant.com/wix/tutorial/com-expression-syntax-miscellanea/expression-syntax/,相关MSI位于https://msdn .microsoft.com/en-us/library/windows/desktop/aa369297%28v=vs.85%29.aspx (2认同)

ahm*_*md0 132

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

在此输入图像描述

假设完全修复和卸载属性的实际值可能是:

在此输入图像描述

WiX的表达式语法文件说:

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

Windows Installer指南中记录了这些属性(例如,已安装)

编辑:对第一张表进行小幅修正; 很明显,"卸载"也可能只是REMOVE存在True.

  • “升级”一栏,是老版本卸载顺序还是新版本安装顺序? (3认同)
  • REMOVE似乎也适用于Change (2认同)

cse*_*ton 48

您可以使用自定义操作执行此操作.您可以在以下位置为自定义操作添加参考<InstallExecuteSequence>:

<InstallExecuteSequence>
...
  <Custom Action="FileCleaner" After='InstallFinalize'>
          Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
Run Code Online (Sandbox Code Playgroud)

然后,您还必须在以下位置定义您的操作<Product>:

<Product> 
...
  <CustomAction Id='FileCleaner' BinaryKey='FileCleanerEXE' 
                ExeCommand='' Return='asyncNoWait'  />
Run Code Online (Sandbox Code Playgroud)

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

<Product> 
...
  <Binary Id="FileCleanerEXE" SourceFile="path\to\fileCleaner.exe" />
Run Code Online (Sandbox Code Playgroud)

真正的诀窍是Installed AND NOT UPGRADINGPRODUCTCODE自定义操作的条件,没有你的操作将在每次升级时运行(因为升级实际上是卸载然后重新安装).如果要删除文件,可能在升级期间不希望出现这种情况.

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

  • 这不起作用.当你想要执行一个安装在你自己的安装文件夹中的fileCleaner.exe时,这将是一个鸡与蛋的问题:`CustomAction`将被执行"After ='InstallFinalize'".此时,将从"安装"文件夹中删除所有文件.还有fileCleaner.exe.因此您无法通过CustomAction执行它.这个答案完全错了.我想知道42个赞成票! (4认同)
  • 25赞成但不是公认的答案.欢迎来到安装人员的世界!:) (3认同)

Rob*_*ing 39

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

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

REMOVE ~= "ALL"
Run Code Online (Sandbox Code Playgroud)

〜=表示比较不区分大小写(即使我认为ALL总是上限).有关更多信息,请参阅有关条件语法MSI SDK文档.

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


Bil*_*ell 10

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

<!-- truth table for installer varables (install vs uninstall vs repair vs upgrade) /sf/answers/1232563461/ -->
 <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>
Run Code Online (Sandbox Code Playgroud)

以下是一些示例用法:

  <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>
Run Code Online (Sandbox Code Playgroud)

问题: