我写了一个自定义操作来帮助我的产品升级(从1.0升级到1.1)。现在,我需要从1.1升级到1.2,但是现有的卸载程序在升级过程中会失败。我的自定义操作的执行条件错误。 (经验教训,在部署之前始终测试升级到下一个版本)。
现在,看来我最好的选择是修改现有.msi中的InstallExecuteSequence表以禁用失败的自定义操作。我必须创建另一个自定义操作来浏览注册表,在C:\中找到现有的.msi。 Windows \ Installer,对其进行修补,然后继续进行升级。这听起来像是一个可怕的,容易出错的解决方案,但是我真的很茫然。这本应是从远程云推送的自动无提示升级。
另一种选择是编写批处理脚本以卸载现有产品,然后执行新的安装程序。
有什么建议吗?
编辑,这里已经回答了这个问题:I screwed up, how can I uninstall my program?
答案 0 :(得分:1)
支持的方法是补丁(我的意思是MSP文件,而不是编码来更改缓存的MSI文件)。到目前为止,这是摆脱困境的最直接方法。之后,进行升级。使用WiX,您可能可以将MSP和升级捆绑在一起。
无论如何,您不会与其他MSI一起进行建议的更改。一个小的可执行文件可以完成您的建议,并且:
MsiGetProductInfo(产品代码,...,INSTALLPROPERTY_LOCALPACKAGE)
是查找缓存的MSI的方式。
答案 1 :(得分:1)
条件 :您对失败的自定义操作设置了什么条件?更重要的是,您打算使用什么新条件? 听起来像常规卸载有效,但主要升级失败吗? ?典型的问题是卸载完全失败,然后通常的解决方案是次要升级,我将对此进行快速介绍。< / p>
次要升级 :通常,我使用的是次要升级,以解决当前安装(取消)安装顺序中的任何错误( 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在这里的回答说明了在应用下一版本的Windows XP之前,如何难以确保包装盒中存在次要升级。您的软件: InstallShield fails because of a bad uninstall。他建议使您的程序包更好地检测是否可以安全地应用新的升级。
某些链接 :
答案 2 :(得分:0)
这是我正在使用的一种黑客工具,但根据上面的答案,它似乎不是首选方式。
[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是在主要升级期间导致卸载失败的属性,因为此属性传递给卸载程序并包含 new 产品代码;在我的情况下为v1.2的产品代码。这是我的安装程序文件中的自定义操作定义。
<CustomAction Id="Patch11Installer" Return="check" Impersonate="yes" Execute="immediate" BinaryKey="MyUpgradeCustomActions" DllEntry="Patch11Installer" />
我将按照其他答案中的建议研究实施次要升级。我只是想把这个解决方案留在这里。