无法在 UPGRADINGPRODUCTCODE、WIX_UPGRADE_DETECTED 中获取 MSI 属性 [英] Failed to get MSI property in UPGRADINGPRODUCTCODE, WIX_UPGRADE_DETECTED

查看:16
本文介绍了无法在 UPGRADINGPRODUCTCODE、WIX_UPGRADE_DETECTED 中获取 MSI 属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在升级过程中跳过一些自定义操作,uninstallDriver,为此我尝试检索属性 WIX_UPGRADE_DETECTEDUPGRADINGPRODUCTCODE,但两者都没有设置.

I wanted to skip some of my custom actions during upgrade, uninstallDriver, to achieve this I have tried to retrieve property WIX_UPGRADE_DETECTED and UPGRADINGPRODUCTCODE, but both of them are not set.

示例代码:

UninstallDriver(MSIHANDLE hInstall)  
{
   char szBuff[1024]; DWORD dwValue = 0;

   OutputDebugStringA("UninstallDriver");
   MsiGetPropertyA(hInstall, "UPGRADINGPRODUCTCODE", szBuff, &dwValue);
   OutputDebugStringA("UPGRADINGPRODUCTCODE");OutputDebugStringA(szBuff);

   MsiGetPropertyA(hInstall, "WIX_UPGRADE_DETECTED", szBuff, &dwValue);
   OutputDebugStringA("WIX_UPGRADE_DETECTED");OutputDebugStringA(szBuff);

   result = UninstallDriver();

   return result;
}

而我的 customAction 是,

And my customAction is,

<Custom Action='UninstallMYDriverAction'
 After='InstallInitialize'>
        REMOVE~="ALL" OR REINSTALL</Custom>

推荐答案

忽略调试字符串,更容易看出缓冲区处理不正确.我建议还输出 MsiGetPropertyA() 的返回值和 dwValue 中的值以确认,但这是我认为正在发生的事情(评论参考 dwValue):

Ignoring the debug strings, it's easier to see that the buffer handling is incorrect. I would suggest also outputting the return values from MsiGetPropertyA() and the value in dwValue to confirm, but here's what I think is happening (comments refer to dwValue):

char szBuff[1024]; DWORD dwValue = 0;
MsiGetPropertyA(hInstall, "UPGRADINGPRODUCTCODE", szBuff, &dwValue); // passes 0, updated to ?x?
MsiGetPropertyA(hInstall, "WIX_UPGRADE_DETECTED", szBuff, &dwValue); // passes ?x?, updated to ?y?

当请求 UPGRADINGPRODUCTCODE 属性并声明缓冲区长度为零时,提取将永远不会成功,因为它必须始终至少接受一个空字符.因此这将返回 ERROR_MORE_DATA 并将 dwValue 设置为不包括空字符 (?x?) 的长度.

When requesting UPGRADINGPRODUCTCODE property with a claimed buffer length of zero, the fetch will never succeed as it must always accept at least a null character. Thus this will return ERROR_MORE_DATA and set dwValue to the length excluding a null character (?x?).

然后它将请求 WIX_UPGRADE_DETECTED 的值,并声明缓冲区长度为 (?x?).如果新长度 (?y?) 小于旧长度 (?x?) 您将在缓冲区中获取其内容;否则它也只会查询这个新属性的长度.

Then it will request the value of WIX_UPGRADE_DETECTED with a claimed buffer length of (?x?). If the new length (?y?) is less than the old length (?x?) you'll get its contents in your buffer; otherwise it will also just query the length of this new property.

由于 WIX_UPGRADE_DETECTED 包含一个或多个 GUID 的列表,而 UPGRADINGPRODUCTCODE 仅包含一个,并且此代码从不增加 dwValue 以说明null,只有当后者为 ?y? 为 0(空)且 ?x? 为非空时才可能成功.但请注意,第二次调用传递了一个未经验证的值作为缓冲区的长度,这种模式是等待发生的缓冲区溢出.

Since WIX_UPGRADE_DETECTED contains a list of one or more GUIDs, and UPGRADINGPRODUCTCODE only contains one, and this code never increments dwValue to account for the null, it will only possibly succeed if the latter is ?y? is 0 (empty) and ?x? is non-empty. But note that this second call passed an unverified value as the length of your buffer, this pattern is a buffer overflow waiting to happen.

所以修复你的缓冲区处理.我喜欢使用的模式(如下)类似于 Stein 描述的模式,但如果我知道缓冲区的良好默认大小,则避免第二次调用.在您的情况下,听起来您对 1024 元素缓冲区很满意,但请考虑您是否需要处理超过 1024/len(GUID) 相关的升级代码.

So fix your buffer handling. The pattern I like to use (below) is similar to what Stein describes, but avoids the second call if I know a good default size for the buffer. In your case, it sounds like you're happy with the 1024 element buffer, but do consider if you ever need to handle more than 1024 / len(GUID) related upgrade codes.

(我猜你没问题.但至少要考虑清楚.即使 GUID 是 ASCII 所以内容无关紧要,请这些天请建立 UNICODE...)

(My guess is you're fine. But at least think it through. And even though GUIDs are ASCII so the contents won't matter, please please please build UNICODE these days...)

WCHAR szBuf[1024];
DWORD cchBuf = 1024; // or _countof(szBuf);
DWORD dwErr = MsiGetPropertyW(hInstall, L"UPGRADINGPRODUCTCODE", szBuf, &cchBuf);
if (dwErr != ERROR_MORE_DATA) {
    // exercise: increment cchBuf for null, adjust buffer, call MsiGetPropertyW again
}
if (dwErr != ERROR_SUCCESS) {
    // per https://docs.microsoft.com/en-us/windows/desktop/msi/custom-action-return-values
    return ERROR_INSTALL_FAILURE;
}

// reset buffer length for next call, in case second property is longer than first
cchBuf = 1024;
dwErr = MsiGetPropertyW(hInstall, L"WIX_UPGRADE_DETECTED", szBuf, &cchBuf);
// : : :

这篇关于无法在 UPGRADINGPRODUCTCODE、WIX_UPGRADE_DETECTED 中获取 MSI 属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆