我想修改MSI安装程序(通过WiX创建)以在卸载时删除整个目录。
我了解WiX中的RemoveFile
和RemoveFolder
选项,但这些选项不够强大,无法递归删除安装后创建内容的整个文件夹。
我注意到了类似的堆栈溢出问题,即在卸载WiX时删除文件,但是我想知道是否可以更简单地通过调用批处理脚本来删除文件夹来完成。
这是我第一次使用WiX,但我仍然习惯于自定义操作。将在卸载时运行批处理脚本的自定义操作的基本示例是什么?
我想修改MSI安装程序(通过WiX创建)以在卸载时删除整个目录。
我了解WiX中的RemoveFile
和RemoveFolder
选项,但这些选项不够强大,无法递归删除安装后创建内容的整个文件夹。
我注意到了类似的堆栈溢出问题,即在卸载WiX时删除文件,但是我想知道是否可以更简单地通过调用批处理脚本来删除文件夹来完成。
这是我第一次使用WiX,但我仍然习惯于自定义操作。将在卸载时运行批处理脚本的自定义操作的基本示例是什么?
Answers:
编辑:也许看看下面立即给出的答案。
长期以来,这个话题一直让人头疼。我终于弄明白了。在线上有一些解决方案,但没有一个真正有效。当然也没有文档。因此,在下表中,建议使用几个属性,以及它们在各种安装方案中的值:
因此,在我的情况下,我希望仅在卸载时运行的CA-不能升级,不能修复或修改。根据上表我不得不使用
<Custom Action='CA_ID' Before='other_CA_ID'>
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
而且有效!
yaluna的答案存在多个问题,属性名称也区分大小写,Installed
拼写正确(INSTALLED
不起作用)。上表应该是这样的:
同样假设完全修复和卸载属性的实际值可能是:
该WiX的表达式语法文件说:
在这些表达式中,可以使用属性名称(请记住,它们是区分大小写的)。
这些属性记录在Windows Installer指南中(例如已安装)
编辑:对第一张桌子的小修正;显然,仅REMOVE
存在也会发生“卸载” True
。
您可以通过自定义操作来执行此操作。您可以在下面的自定义操作中添加参考<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提示”窗口在刷新时闪烁您的安装程序运行。
CustomAction
将执行“ After ='InstallFinalize'”。此时,所有文件将从“安装”文件夹中删除。也是fileCleaner.exe。因此,您将无法通过CustomAction执行它。这个答案是完全错误的。我想知道42次投票!
批处理脚本的最大问题是在用户单击“取消”时处理回滚(或在安装过程中出现问题)。解决此情况的正确方法是创建一个CustomAction,该操作将临时行添加到RemoveFiles表中。这样,Windows Installer即可为您处理回退案例。当您看到解决方案时,它变得异常简单。
无论如何,要使操作仅在卸载期间执行,请添加带有以下内容的Condition元素:
REMOVE ~= "ALL"
〜=表示不区分大小写(尽管我认为ALL始终是大写)。有关更多信息,请参见有关条件语法的MSI SDK文档。
PS:从来没有出现过我坐下来想过:“哦,批处理文件将是安装软件包中的一个很好的解决方案。实际上,找到其中包含批处理文件的安装软件包只会鼓励我退回产品以获得退款。
这是我制作的一组属性,使用起来比内置的东西更直观。条件基于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>
问题: