С++ Чтение значения строки реестра в char*

Возможный дубликат:
Как сравнивать строки


Я хочу сравнить значения строки реестра, и если они были одинаковыми, появится окно сообщения
В настоящее время я использую эту функцию, она возвращает значение правильно, но всякий раз, когда я хочу их сравнить, результат сравнения всегда неверен.

char* GetRegistry(char* StringName)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
char value[1024];
DWORD value_length = 1024;
const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)&value, &value_length);
return  value;
}


Я использую это, чтобы сравнить их

if (GetRegistry("First") == GetRegistry("Second"))
{
MessageBox(NULL,":|",":|",1);
}


Но MessageBox всегда появляется Значения разные


Любая помощь приветствуется.


person Shahriyar    schedule 18.10.2012    source источник
comment
Как сравнивать строки в C++   -  person Roman R.    schedule 18.10.2012
comment
Будьте точны, у вас даже нет SZ_STRING, так зачем помещать это в заголовок.   -  person Roman R.    schedule 18.10.2012
comment
Я хотел написать REG_SZ , но случайно написал SZ_STRING   -  person Shahriyar    schedule 18.10.2012
comment
@Shahriyar: но я случайно написал SZ_STRING Под вашим сообщением слева есть набор текстовых кнопок. Один из них говорит редактировать. Это было бы идеальное время, чтобы попробовать это...   -  person dmckee --- ex-moderator kitten    schedule 18.10.2012


Ответы (3)


При использовании std::string сравнение будет вести себя так, как вы ожидали. Также это исправит еще одну ошибку, когда функция возвращает указатель на локальный буфер.

std::string GetRegistry(const char* StringName)
{
....
return std::string(value);
}
person Andrey    schedule 18.10.2012
comment
Спасибо, но я использую его в dll win32, и когда я хочу использовать ваш код, он говорит мне, что в пространстве имен std нет строки-члена - person Shahriyar; 18.10.2012
comment
@Shahriyar: Ты #include <string> ? - person Andrey; 18.10.2012
comment
Спасибо, теперь я сделал, я собираюсь снова проверить работу - person Shahriyar; 18.10.2012
comment
Ошибка при использовании if (strcmp(GetRegistry(First), GetRegistry(Second)) == 0) {} Ошибка: нет подходящей функции покрытия из std::string в const char * - person Shahriyar; 18.10.2012
comment
@Shahriyar: если вы возвращаете std::string из своей функции GetRegistry(), вы можете просто использовать operator==; вы не должны не использовать strcmp() в этом случае. - person Mr.C64; 18.10.2012
comment
Наконец-то это сработало, спасибо всем за помощь - person Shahriyar; 18.10.2012

GetRegistry() возвращает char*, поэтому на самом деле вы сравниваете указатели с operator==. Вы должны использовать strcmp() для необработанных сравнений строк char* в стиле C, или лучше использовать надежный класс строк C++, например CString или std::[w]string.

Вот возможная переработка вашей функции с использованием ATL CString:

#include <atlbase.h>
#include <atlstr.h>

CString GetRegistry(LPCTSTR pszValueName)
{
    // Try open registry key
    HKEY hKey = NULL;
    LPCTSTR pszSubkey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions");
    if ( RegOpenKey(HKEY_LOCAL_MACHINE, pszSubkey, &hKey) != ERROR_SUCCESS )
    {
        // Error:
        // throw an exception or something...
        //
        // (In production code a custom C++ exception 
        // derived from std::runtime_error could be used)
        AtlThrowLastWin32();
    }

    // Buffer to store string read from registry
    TCHAR szValue[1024];
    DWORD cbValueLength = sizeof(szValue);

    // Query string value
    if ( RegQueryValueEx(
            hKey,
            pszValueName, 
            NULL, 
            NULL, 
            reinterpret_cast<LPBYTE>(&szValue), 
            &cbValueLength) 
         != ERROR_SUCCESS )
    {
        // Error
        // throw an exception or something...
        AtlThrowLastWin32();
    }

    // Create a CString from the value buffer
    return CString(szValue);
}

И тогда вы можете назвать это так:

if ( GetRegistry(_T("First")) == GetRegistry(_T("Second")) )
    ...

Обратите внимание, что этот код будет компилироваться как в сборках ANSI/MBCS, так и в сборках Unicode (он основан на модели Win32 TCHAR).

person Mr.C64    schedule 18.10.2012
comment
не могу открыть исходный файл atlstr.h не могу открыть исходный файл atlbase.h Должен ли я что-то скачать? - person Shahriyar; 18.10.2012
comment
@Shahriyar: Вам нужен ATL. Если вы используете какую-либо коммерческую версию Visual Studio, она у вас есть. Но ATL недоступен в бесплатных версиях Express. (Однако кажется, что вы можете загрузить WDK и получить из него заголовки ATL: см. инструкции по сборке Google Chrome для Windows, в которых есть раздел по использованию Visual C++ 2012 Express.) - person Mr.C64; 18.10.2012
comment
Большое спасибо, моя проблема решена - person Shahriyar; 18.10.2012

У вас есть пара проблем с этим исходным кодом.

Во-первых, у вас есть функция с локальной переменной, переменной в стеке, которая возвращает адрес этой переменной, но когда функция возвращается, переменная исчезает, и адрес больше недействителен.

Следующая проблема заключается в том, что вы не сравниваете строки символов. Вместо этого вы сравниваете адрес, возвращаемый функцией, и, если вам повезет, адрес может быть таким же. Поскольку вы вызываете функцию дважды подряд, вам повезло, поэтому адрес один и тот же.

Я предлагаю вам сделать следующее: (1) создать две строки локальных символов в вашей функции, которая вызывает функцию GetRegistry(), и (2) изменить функцию GetRegistry(), чтобы она использовала эти буферы, а не свои собственные. Таким образом, код будет выглядеть примерно так:

char registryEntryOne[1024];
char registryEntryTwo[1024];
DWORD dwRegistryEntryOneLen;
DWORD dwRegistryEntryTwoLen;

registryEntryOne[0] = 0;   // init the registry entry to zero length string
registryEntryTwo[0] = 0;

dwRegistryEntryOneLen = sizeof(registryEntryOne);
GetRegistry ("First", registryEntryOne, &dwRegistryEntryOneLen);
dwRegistryEntryTwoLen = sizeof(registryEntryTwo);
GetRegistry ("Second", registryEntryTwo, &dwRegistryEntryTwoLen);

// two strings are equal if:
//   the lengths are the same
//   at least one of the lengths is non-zero
//   the bytes are the same in the same order
if (dwRegistryEntryOneLen && dwRegistryEntryOneLen == dwRegistryEntryTwoLen && memcmp (registryEntryOne, registryEntryTwo, dwRegistryEntryOneLen) == 0) {
    // strings are equal
} else {
    // strings are not equal
}

Функция GetRegistry() будет выглядеть примерно так:

char* GetRegistry(char* StringName, char *valueBuffer, DWORD *value_length)
{
    DWORD dwType = REG_SZ;
    HKEY hKey = 0;
    const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";

    RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
    RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)valueBuffer, value_length);
    return  valueBuffer;
}
person Richard Chambers    schedule 18.10.2012
comment
Эта функция дает мне пару ошибок - person Shahriyar; 18.10.2012