首页 文章

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

提问于
浏览
141

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

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

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

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

6 回答

  • 179

    EDIT :也许看下面的答案 .


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

    alt text

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

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

    它奏效了!

  • 47

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

    enter image description here

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

    enter image description here

    WiX Expression Syntax文件说:

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

    Windows Installer指南中记录了这些属性(例如Installed

    编辑:对第一张表进行小幅修正;显然"Uninstall"也可能发生 REMOVE 正在 True .

  • 0

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

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

    然后你还必须在 <Product> 下定义你的Action:

    <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提示”窗口闪烁而安装程序运行 .

  • 2

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

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

    REMOVE ~= "ALL"
    

    〜=表示比较不区分大小写(即使我认为ALL总是上限) . 有关更多信息,请参阅MSI SDK documentation about Conditions Syntax .

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

  • 35

    这是我制作的一组属性,使用起来比内置的东西更直观 . 条件基于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>
    

    问题:

  • 114

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

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

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

相关问题