【发布时间】:2013-10-31 01:22:22
【问题描述】:
我的产品有一个帮助程序可执行文件来卸载所有相关的子产品。我根据所有子产品的升级代码卸载。
首先,我使用MsiEnumRelatedProducts 函数从升级代码中获取产品代码。然后我尝试使用MsiConfigureProductEx函数卸载产品。
问题是MsiConfigureProductEx 正在返回错误。
调用函数:MsiConfigureProductsEx
返回码:1605 (0x00000645)
说明:此操作仅对当前安装的产品有效。
为什么MsiEnumRelatedProducts 返回一个无效的产品代码?我搜索了 Windows 注册表以查看是否存在此类产品代码。没有。如何调试问题?
编辑:添加了重现问题的最少代码。
// UpgradeCodes is an array having upgrade codes of all modules.
TCHAR lpProductCode[GUID_STR_LENGTH];
const TCHAR tszNoReboot[] = _T("REMOVE=ALL REBOOT=ReallySuppress DISABLE_REBOOT_PROMPT=1");
for (size_t i = 0; i < sizeof(UpgradeCodes) / sizeof(UpgradeCodes[0]); i++)
{
tstring tstrUpgradeCode = UpgradeCodes[i];
DWORD dwIndex = 0;
size_t status;
// for each of the upgrade code, get all the products
do
{
status = MsiEnumRelatedProducts(UpgradeCodes[i],
0,
dwIndex,
lpProductCode);
if (ERROR_SUCCESS == status)
{
UINT uiReturn = MsiConfigureProductEx(lpProductCode,
INSTALLLEVEL_DEFAULT,
INSTALLSTATE_DEFAULT,
tszNoReboot);
if (ERROR_SUCCESS_REBOOT_REQUIRED == uiReturn)
{
// prompt for reboot at the end of all modules uninstallation.
}
if (ERROR_SUCCESS != uiReturn)
{
// log message with return code.
// Error Code: 1605 is coming from here.
}
}
}while (ERROR_NO_MORE_ITEMS != status);
}
【问题讨论】:
-
请出示您的实际代码。您是否在调用
MsiConfigureProductEx()之前检查MsiEnumRelatedProducts()的返回值是否有错误?你传递给MsiConfigureProductEx()的参数是什么? -
@RemyLebeau 添加了重现问题的代码。
-
@RemyLebeau 我从添加或删除程序中手动卸载了一个子模块,然后我运行了我的实用工具。从那时起,这个问题就出现了。我检查了 Windows 注册表中的升级代码,以查看失败场景的升级代码是否存在。没有这样的升级代码。因此,
MsiEnumRelatedProducts不应该返回任何产品代码。 Windows 安装程序在某处缓存此信息。 -
The documentation 说“这个函数列出了当前安装的和广告在其属性表中具有指定 UpgradeCode 属性的产品”。所以它确实会返回未安装的产品。尝试致电
MsiQueryProductState以查看 MSI 认为产品处于什么状态。不要卸载任何未安装的产品。 -
您能否尝试完整阅读此主题(使用 cmets):stackoverflow.com/questions/22583822/…。重大升级失败并注册了两个版本的应用程序并非不可能。我对此表示怀疑,但请务必阅读该主题,因为问题似乎很重要。我稍后再回来查看。
标签: windows winapi windows-installer installation