2013-05-08 3 views
0

У меня есть установщик, созданный с использованием Installshield 2012, который во многом зависит от значения ключа реестра, написанного каким-либо другим приложением, разработанным внутри компании. Я использую API-интерфейс RegDBGetKeyValueEx для получения значения.Недопустимые/чужие символы из значения, полученного из реестра

Это значение представляет собой путь к каталогу, который, как гарантируется, имеет обратную косую черту. Это значение служит TARGETDIR для моего установщика.

Проблема заключается в том, что я часто вижу иностранного персонажа (китайца, японца или корейца), прилагаемого к обратной косой чертой. Это приводит к тому, что мой TARGETDIR содержит внешний символ. Это загрязняет мою установку.

Я чувствую, что это некоторая ошибка с API-интерфейсом Installscript, который неправильно преобразует значение реестра.

Просьба представить несколько материалов, чтобы я мог найти причину проблемы.

EDIT 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 

EDIT 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); 
+0

Are вы уверены, что значение ключа реестра, написанного другим в домашнем приложении, является правильным? Я помню, что у меня были проблемы с функцией RegSetValueEx, когда я написал строку, указав длину строки, а не длину строки + 1 для параметра cbData. –

+0

Если вы посмотрите в реестре, вы видите иностранного персонажа? Если нет, то, скорее всего, вы читаете/интерпретируете неверное значение в вашем коде. Можете ли вы показать свой фактический код чтения? –

+0

Почему вы запрашиваете доступ к «KEY_WRITE», когда вы на самом деле ничего не пишете на ключ? Используйте 'KEY_READ' самостоятельно или даже просто' KEY_QUERY_VALUE'. Чем меньше разрешений вы запрашиваете, тем лучше ваши шансы открыть ключ в более жестких средах безопасности. Кроме того, вы пропустите ключевой дескриптор, если 'RegOpenKeyEx()' успешно, но 'RegQueryValueEx()' терпит неудачу. –

ответ

1

При назначении данных реестра вашей переменной m_reqPath вы обрабатываете ее как символьные данные с нулевым символом. Однако строковые данные, считанные RegQueryValueEx(), равны , а не, гарантированно заканчивается на нуль, если исходный писатель данных не включил его. Это четко указано в documentation.

Скорее всего, строковые данные, которые вы читаете в реестре, это не с нулевым завершением, поэтому вы в конечном итоге копируете случайные данные из конца вашего буфера. Чтобы учесть эту возможность, вам нужно выделить дополнительное пространство в своем буфере и поместить свой нулевой ограничитель в конце любых данных, которые вы действительно читали. Если данные правильно завершены нулем, то ваш терминатор будет просто избыточным.

Вы также пропускаете открытый ключ ключа реестра, если 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); 
} 
+0

Да, исходный вызов 'RegSetValueEx() был опущен нулевым терминатором. Это не редкость, поэтому Microsoft создала 'RegGetValue()' для решения этой проблемы, поэтому программистам больше не придется об этом беспокоиться. –

+0

Спасибо Remy.I обновил сообщение. Я также заметил, что после комментария Майкла Уолца, что RegSetValueEx был передан неверный счетчик байтов. Я считаю, что это должно быть правильно [m_reqLeicaPath.GetLength() + 1]. Единственная проблема со всем этим заключается в том, что это ошибка INTERMITTENT. Это происходит не последовательно. Я никогда не мог воспроизвести проблему нигде. RegGetValue кажется многообещающим. Я посмотрел на него. Это приложение является чьей-то ответственностью, и я должен будет подать сильное дело, чтобы заставить их внести изменения. – msiyer

0

На некоторых кодовых страницах символ валюты - это то же самое значение байта в ASCII, что и обратная косая черта. Если вы используете Unicode-функции, это не должно быть проблемой.

Для получения дополнительной информации см. http://www.siao2.com/2005/09/17/469941.aspx.

+0

Installshield Engine совместим с Unicode. Я вижу, что инородный персонаж обратился к обратной косой чертой. Обратная косая черта не заменяется символом. – msiyer

Смежные вопросы