Сообщений 0    Оценка 141        Оценить  
Система Orphus

Как удалить ключ из реестра?

Автор: Александр Шаргин
Опубликовано: 18.02.2001
Исправлено: 13.03.2005
Версия текста: 1.0

Для удаления ключей из реестра предназначена функция RegDeleteKey из Win32 API. В качестве параметров эта функция получает дескриптор родительского ключа, а также имя подключа, подлежащего удалению. В качестве дескриптора родительского ключа можно передать константу, соответствующую одному из основных разделов реестра (HKEY_CLASSES_ROOT, HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER и т. п.), а также любой другой дескриптор, полученный в результате вызова функции RegOpenKey(Ex).

В качестве примера рассмотрим код, удаляющий ключ "Some key" из раздела HKEY_LOCAL_MACHINE.

RegDeleteKey(HKEY_LOCAL_MACHINE, "Some key");

Функция RegDeleteKey удобна, но имеет один серьёзный недостаток: под Windows NT/2000 она удаляет из реестра только пустые ключи, то есть ключи, не содержащие подключей.

Альтернативой RegDeleteKey является функция SHDeleteKey из shell API (объявлена в файле shlwapi.h). Она используется в точности так же, как и RegDeleteKey, например:

#include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")

...


SHDeleteKey(HKEY_LOCAL_MACHINE, "Some key");

Функция SHDeleteKey корректно удаляет непустые ключи из реестра как под Windows 9x, так и под Windows NT/2000, но, к сожалению, при её использовании возникает другая проблема: она появилась в библиотеке shlwapi.dll только начиная с версии 4.71. А это означает, что функция SHDeleteKey будет доступна под Windows 95 и Windows NT только при наличии Internet Explorer версии 4.0 и выше.

Если прямое применение функций RegDeleteKey и SHDeleteKey не возможно, остаётся применить стандартный в таких случаях подход: написать свою функцию, которая будет удалять сначала все подключи некоторого ключа, я затем и сам ключ. Алгоритм работы этой функции может выглядеть примерно так: получаем список всех подключей заданного, рекурсивно вызываем для каждого из них нашу функцию удаления, а затем удаляем сам ключ при помощи RegDeleteKey.

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

LONG DeleteKey(HKEY hParentKey, LPCTSTR szKey)
{
    TCHAR *szSubKey = NULL;
    HKEY hKey = NULL;
    LONG nRes;

    __try
    {
        nRes = RegOpenKeyEx(hParentKey, szKey, 0, KEY_ENUMERATE_SUB_KEYS|KEY_READ | KEY_WRITE, &hKey);
        if(nRes != ERROR_SUCCESS)
            __leave;

        DWORD nMaxLen;
        RegQueryInfoKey(
            hKey, NULL, NULL, NULL, NULL,
            &nMaxLen, NULL, NULL, NULL, NULL, NULL, NULL);
        nMaxLen++;
        
        szSubKey = new TCHAR[nMaxLen];

        DWORD nSize = nMaxLen;
        FILETIME tTime;

        while((nRes=RegEnumKeyEx(
            hKey, 0, szSubKey, &nSize, 0, NULL, NULL, &tTime)) == ERROR_SUCCESS)
        {
            nRes = DeleteKey(hKey, szSubKey);
            if(nRes != ERROR_SUCCESS)
                __leave;

            nSize = nMaxLen;
        }

        nRes = RegDeleteKey(hParentKey, szKey);
    }
    __finally
    {
        if(szSubKey != NULL)
            delete [] szSubKey;

        if(hKey != NULL)
            RegCloseKey(hKey);

        return nRes;
    }
}

Если эта функция кажется вам слишком сложной, вам будет приятно узнать, что Microsoft уже написала её за вас. Соответствующая функция называется RecurseDeleteKey и является членом класса CRegKey из библиотеки ATL. Пример её использования приведён ниже.

#include <atlbase.h>

...

CRegKey rKey;
rKey.Attach(HKEY_LOCAL_MACHINE);
rKey.RecurseDeleteKey("Some key");

Хотя класс CRegKey входит в библиотеку ATL, он целиком реализован в заголовочном файле atlbase.h и не использует ссылается на другие классы ATL. Поэтому его использование не приведёт к "раздуванию" кода вашей программы. Следует, однако, иметь в виду, что в функции RecurseDeleteKey на имя подключа выделяется ровно 256 байт, что теоретически может привести к проблемам под Windows NT/2000, где длина имени ключа может быть и больше. Хотя на практике такие длинные ключи практически никогда не встречаются.

Описанных способов оказывается вполне достаточно, чтобы решить поставленную задачу.


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 0    Оценка 141        Оценить