0

我有一个使用 Installshield 2012 创建的安装程序,它在很大程度上取决于由内部开发的其他一些应用程序编写的注册表项的值。我使用 RegDBGetKeyValueEx Installscript API 来获取值。

这个值是保证有一个尾部反斜杠的目录路径。此值用作我的安装程序的 TARGETDIR。

问题是我经常看到一个外来字符(中文、日文或韩文)附加到反斜杠上。这导致我的 TARGETDIR 包含外来字符。这污染了我的安装。

我觉得这是 Installscript API 的一些错误,它错误地转换了注册表值。

请提供一些输入,以便我找到问题的根本原因。

编辑1:

另一个有问题的应用程序是纯 ANSI 应用程序,不支持 Unicode。任何地方都没有指定#define UNICODE。我还检查了编译器参数,没有发现任何与指定的 Unicode 相关的内容。

此应用程序读取一个注册表项并附加一个反斜杠并更新其他项。完成此操作后,我的安装程序将获取写入的值:

if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, csVersKey, 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) &&
        (RegQueryValueEx(hKey, "BasePath", NULL, NULL, (unsigned char *)szTemp, &BufferSize) == ERROR_SUCCESS))
    {
        m_reqPath = szTemp;
        if (m_regPath.Right(1) != "\\") m_reqPath += "\\";
        m_reqMachinePath = m_reqPath + "\\" + m_reqMachine + "\\";
        m_reqHardwarePath = m_reqMachinePath + HARDWARE_DIRECTORY;
        m_reqManualPath = m_reqMachinePath + MANUAL_DIRECTORY;
        m_reqVersionPath = m_reqMachinePath + m_reqVersion + "\\";
        m_reqFirmwarePath = m_reqVersionPath + FIRMWARE_DIRECTORY;
        m_RegVersDirectory = m_reqVersionPath + PROGRAM_DIRECTORY;
        RegCloseKey(hKey);
    }

然后将上述代码中更新的值写入注册表。获取这些值的 Installscript 代码是:

if ((RegDBKeyExist(szBaseKey ^ szRegKey) = 1) && (RegDBGetKeyValueEx(szBaseKey ^ szRegKey, "ReqPath", nTemp, szTemp, nvSize) = 0)) then

编辑2:

设置注册表值的方式似乎是错误的:

RegSetValueEx(hKey, LEICA_PATH, 0, REG_SZ, (const unsigned char*)m_reqLeicaPath.GetBuffer(m_reqLeicaPath.GetLength()), m_reqLeicaPath.GetLength());

我觉得正确的代码应该是:

RegSetValueEx(hKey, LEICA_PATH, 0, REG_SZ, (const unsigned char*)m_reqLeicaPath.GetBuffer(m_reqLeicaPath.GetLength()), m_reqLeicaPath.GetLength() + 1);
4

2 回答 2

1

将注册表数据分配给m_reqPath变量时,您将其视为以空字符结尾的字符数据。但是,如果数据的原始写入者不包含空值,则不RegQueryValueEx()保证读取的字符串数据以空值结尾。这在文档中有明确说明。

您从注册表读取的字符串数据可能不是以空值结尾的,因此您最终会从缓冲区末尾复制随机数据。为了解决这种可能性,您需要在缓冲区中分配额外的空间,并将您自己的空终止符放在您实际读取的任何数据的末尾。如果数据正确地以空值终止,那么您的终止符将只是多余的。

RegOpenKeyEx()如果成功但RegQueryValueEx()失败,您也会泄漏打开的注册表项句柄。

试试这个:

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, csVersKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
    char szTemp[257];
    DWORD BufferSize = 256;

    if (RegQueryValueEx(hKey, "BasePath", NULL, NULL, (BYTE*)szTemp, &BufferSize) == ERROR_SUCCESS)
    {
        szTemp[BufferSize] = '\0';
        m_reqPath = szTemp;
        ...
    }

    RegCloseKey(hKey);
}

要完全避免这个问题,RegGetValue()请改用它,它会为您处理空终止符:

char szTemp[257];
DWORD BufferSize = sizeof(szTemp);

if (RegGetValue(HKEY_LOCAL_MACHINE, csVersKey, "BasePath", RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ, NULL, szTemp, &BufferSize) == ERROR_SUCCESS)
{
    m_reqPath = szTemp;
    ...
}

或者:

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, csVersKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
    char szTemp[257];
    DWORD BufferSize = sizeof(szTemp);

    if (RegGetValue(hKey, NULL, "BasePath", RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ, NULL, szTemp, &BufferSize) == ERROR_SUCCESS)
    {
        m_reqPath = szTemp;
        ...
    }

    RegCloseKey(hKey);
}
于 2013-05-08T18:22:12.943 回答
0

在某些代码页中,货币符号与反斜杠在 ASCII 中的字节值相同。如果您使用的是 Unicode 函数,这应该不是问题。

有关详细信息,请参阅http://www.siao2.com/2005/09/17/469941.aspx

于 2013-05-08T06:46:31.017 回答