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

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

问题描述

我想跳过升级过程中的一些自定义操作, uninstallDriver ,为实现此目的,我尝试检索属性 WIX_UPGRADE_DETECTED UPGRADINGPRODUCTCODE ,但都未设置。

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 来表示空值,它只会如果后者为?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天全站免登陆