【问题标题】:Existing Uninstaller Broken During Upgrade - Patch MSI?现有卸载程序在升级期间损坏 - 补丁 MSI?
【发布时间】:2019-01-04 15:02:00
【问题描述】:

我编写了一个自定义操作来帮助我的产品升级(从 1.0 到 1.1)。现在我需要从 1.1 升级到 1.2,但现有的卸载程序在升级过程中失败。我的自定义操作的执行条件错误。 (经验教训,在部署之前总是测试升级到下一个版本)。

现在看来我最好的选择是修改现有 .msi 中的 InstallExecuteSequence 表以禁用失败的自定义操作。我必须创建 另一个 自定义操作来浏览注册表,在 C:\ 中找到现有的 .msi Windows\Installer,修补它,然后继续升级。这听起来像是一个糟糕的、容易出错的解决方案,但我真的很茫然。这应该是从远程云下推的自动、静默升级。

另一种选择是编写一个批处理脚本来卸载现有产品,然后执行新的安装程序。

有什么建议吗?

编辑这里已经回答了这个问题:I screwed up, how can I uninstall my program?

【问题讨论】:

    标签: wix windows-installer upgrade custom-action


    【解决方案1】:

    执行此操作的受支持方法是补丁(我的意思是 MSP 文件,而不是编码以更改缓存的 MSI 文件)。这是迄今为止摆脱困境的最直接的方法。之后,进行升级。使用 WiX,您可能会将 MSP 和升级放在一个捆绑包中。

    在任何情况下,您都不会使用其他 MSI 进行您提议的更改。一个小的可执行文件可以执行您的建议,并且:

    MsiGetProductInfo (ProductCode, ..., INSTALLPROPERTY_LOCALPACKAGE)

    是您如何找到缓存的 MSI。

    【讨论】:

      【解决方案2】:

      调节:您为失败的自定义操作设置了什么条件?更重要的是,您打算使用的新条件是什么? 听起来常规卸载有效,但大升级失败?典型的问题是卸载完全失败,然后通常的解决方案是小升级,我将快速描述。

      次要升级:通常我使用的是次要升级来修复当前安装(卸载)安装顺序中的任何错误( s)。次要升级不会卸载现有安装,它会“就地”升级它,因此永远不会调用卸载序列,因此您可以避免其所有错误出现。 There is no need to browse to the cached MSI file and hack it manually if you do things correctly in your minor upgrade。如果您使用正确的次要升级命令行进行安装,则 Windows Installer 引擎将自动更新缓存的 MSI。

      未来的升级:如果你把它做得足够简单,一个小升级通常总是有效的,但问题通常是应用它,因为它通常只针对一个单一的、以前的版本。当您进入下一个版本并使用主要升级时,如果您正在升级从未应用过次要升级的安装,您将在卸载时看到原始 MSI 清单本身的错误 - 换句话说,它仍然是安装的最旧版本。这通常由setup.exe 启动器解决,如果需要,它将安装次要升级。坏消息是您需要在以后的每个版本中保留该更新 - 如果您想避免任何升级错误。或者在公司环境中,您将使用分发系统检查盒子上已有的内容并进行相应的安装。 如果您的手动卸载工作正常(但主要升级卸载失败),您需要做的就是将 an uninstall command line to msiexec.exe 作为第一个通过 setup.exe 运行的命令推送我认为。这样就无需在 setup.exe 启动器中包含任何次要升级二进制文件。

      检测并中止?:Michael Urman 的回答解释了在应用下一版本的你的软件: InstallShield fails because of a bad uninstall。他建议让您的软件包更好地检测是否可以安全地应用新升级。


      一些链接

      【讨论】:

      • 现有条件是“UPGRADINGPRODUCTCODE OR WIX_UPGRADE_DETECTED”。我打算将其更改为“WIX_UPGRADE_DETECTED”。是的,定期卸载有效。我可以远程下推并执行批处理脚本。我可以应用一个小升级补丁,然后是大升级。我也可以批量做所有事情:复制旧配置文件,卸载旧版本,安装新版本。我必须修改安装程序以使用命令行上传递的参数静默执行。
      • 哦,那个老栗子。 See here for similar issue(主要为找到此链接的其他人提供链接)。在重大升级期间,UPGRADINGPRODUCTCODE 设置在旧安装程序卸载中,而不是在正在安装的新安装程序中。 因此,从外观上看,您更改的条件意味着您只想在较新的安装程序中运行自定义操作,而不是在旧安装程序的卸载期间运行。还有an example of how complex conditions are hard to test.
      • how to test complex conditions 使用自定义操作在运行时评估条件。靠近底部的“Property Debugger Demo”。正如他们所说,证据就在布丁中 - 我喜欢以各种安装模式(installrepairself-repairmajor upgradepatchuninstalletc...)运行安装程序这些属性评估器自定义操作显示消息框,以便查看运行时发生的情况。不过请记住将它们从您的最终设置中删除:-)。
      【解决方案3】:

      这是我开始工作的一个技巧,但根据上面的答案,这似乎不是首选方式。

      [CustomAction]
      public static ActionResult Patch11Installer(Session session)
      {
          string localPackage = NativeMethods.GetMsiInstallSource("{MY-PRODUCT-CODE}");
          if (String.IsNullOrEmpty(localPackage))
          {
              session.Log("Failed to locate the local package");
              return ActionResult.Failure;
          }
      
          session.Log($"Found local package at {localPackage}");
      
          using (Database database = new Database(localPackage, DatabaseOpenMode.Direct))
          {
              foreach (string action in new string[] { LIST OF CUSTOM ACTION NAMES })
              {
                  session.Log($"Modifying condition for action {action}");
                  database.Execute($"UPDATE InstallExecuteSequence SET Condition='WIX_UPGRADE_DETECTED' WHERE Action='{action}'");
              }
      
              database.Commit();
          }
      
          return ActionResult.Success;
      }
      

      自定义操作调用MsiGetProductInfo 以使用我从安装程序日志文件中获得的 v1.1 产品代码查询 v1.1 MSI。然后,它打开 MSI 数据库并修改 InstallExecuteSequence 表的 Condition 属性以获取失败的自定义操作列表。它将条件从“UPGRADINGPRODUCTCODE OR WIX_UPGRADE_DETECTED”更改为“WIX_UPGRADE_DETECTED”。 UPGRADINGPRODUCTCODE 是在重大升级期间导致卸载失败的属性,因为此属性已传递给卸载程序并包含 产品代码;就我而言,v1.2 的产品代码。这是我的安装程序文件中的自定义操作定义。

      <CustomAction Id="Patch11Installer" Return="check" Impersonate="yes" Execute="immediate" BinaryKey="MyUpgradeCustomActions" DllEntry="Patch11Installer" />
      

      我将考虑按照其他答案中的建议实施小升级。我只是想我会把这个解决方案留在这里。

      【讨论】:

      • 我想如果您在公司环境中,您可以从它自己的可执行文件或脚本(计划任务?登录脚本?)运行它 - 换句话说,根本不需要使用自定义操作。您也可以将其放入您部署一次的自己的“修复程序 MSI”中。顺便说一句,你是如何在你的 MSI 中安排这个的?我希望你在InstallExecuteSequence? (或者该操作不会在静默模式下运行)。另外:即时模式自定义操作不会运行提升 - 它们始终作为启动用户运行(可能恰好是启用 UAC 提升的管理员 - 使其看起来可以工作)。
      • 继续提升:但是通过提升权限安装的标准用户将看到 MSI 失败,因为 “真正的管理员权限” 是必需的,而不仅仅是 “提升的权限”(在安装期间由组策略/活动目录授予的临时管理员权限 - 并且仅适用于 InstallInitializeInstallFinalizeInstallExecuteSequence)。
      猜你喜欢
      • 2011-11-29
      • 1970-01-01
      • 2015-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      相关资源
      最近更新 更多