RegDeleteTree

Esta función no es más que una forma recursiva que tiene la API de Windows para utilizar RegOpenKeyEx, RegEnumKeyEx (Aún no documentada aquí en Wiki) y RegDeleteKeyEx con el objetivo de abrir una Clave indicada en la función, enumerar todas las sub-claves que tenga y eliminarlas una por una junto con sus respectivos Valores de Registro. Quiere decir que podría utilizar la combinación de las tres para llevar a cabo la operación, o bien llamar a esta función que hará el trabajo fácil y rápido, aunque puede ser necesario, de acuerdo a la clave que se le vaya a eliminar sub-claves, utilizar de todas formas la función RegOpenKeyEx. Windows internamente utiliza estas funciones cuando se está trabajando desde el Editor de Registro.

Esta función es la que se debe utilizar cuando queramos borrar todo un árbol de sub-claves, ya que RegDeleteKeyEx vista en otro artículo de Wiki, solo permite borrar una sola sub-clave indicada con todos sus valores.

Declaración

Esta función es realmente sencilla de utilizar, y solo requiere dos variables:

HKEY hKey: Siempre representa el apuntador a una clave de registro que se haya abierto con RegCreateKeyEx o RegOpenKeyEx, aunque también puede tomarse alguna de las ramas predefinidas:

HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS


Si se utiliza RegCreateKeyEx o RegOpenKeyEx, tendríamos que usar la variable declarada de phkResult que tiene el apuntador a toda la clave.

LPCTSTR lpSubKey: Para esta variable es necesario indicarle cuál es el nombre exacto de la clave a la que se le eliminarán todas las sub-claves. Por ejemplo, si deseamos eliminar todo lo que esté dentro de MiSubClave, ubicada en HKEY_CURRENT_USER\MiClave, la declararíamos como: "MiSubClave", pues hKey tendría el retorno de HKEY_CURRENT_USER\MiClave.

Ejemplo práctico

Para ver en acción esta función como corresponde, supongamos que tenemos una clave sub-clave llamada APrincipal en HKEY_CURRENT_USER, y dentro de esta tenemos a la vez dos sub-claves más llamadas Borrar y NoBorrar. Dentro de borrar existe una última sub-clave denominada BorrarA y tiene un valor de tipo DWORD llamado ValorABorrar. La siguiente imagen ilustra un poco lo explicado anteriormente:




Nota: Lo ideal es que creen las claves y valores para hacer las pruebas.

Como el proceso siempre es Abrir > Eliminar, tenemos que abrir la clave HKEY_CURRENT_USER\APrincipal y eliminar todo el árbol que tenga la sub-clave Borrar.

Las declaraciones, según lo explicado anteriormente, y de acuerdo a lo que ya escribí en el artículo dedicado a RegOpenKeyEx, quedarían así:

//Declaración para RegOpenKeyEx
    HKEY hKey = HKEY_CURRENT_USER;
    LPCTSTR lpSubKey = L"APrincipal";
    DWORD ulOptions = 0;
    //samDesired debe tener estos permisos para poder borrar sub-claves y valores:
    REGSAM samDesired = DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE;
    HKEY phkResult;
     
    //Declaración para RegDeleteTree
    LPCTSTR lpSubKey2 = L"Borrar";
    long R2;
 
    //Es necesario hKey, pero ya está declarada por RegOpenKeyEx

Nota: Por supuesto hay que tener en cuenta la declaración del método principal.

Lo primero es buscar y abrir la clave principal, que sería: HKEY_CURRENT_USER\APrincipal, y esto se hace con RegOpenKeyEx llamando la función y enviándole los valores declarados. Para que podamos controlar el resultado, lo guardamos como siempre en una variable R1 de tipo long:

//Abriendo la clave
    long R1 = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, &phkResult);

Con un switch podemos tomar las decisiones adecuadas de acuerdo al código que devuelva RegOpenKeyEx. Si el ID es ERROR_SUCCESS, procedemos a eliminar el árbol y a indicarlo con sus respectivas comprobaciones, de lo contrario, indicamos mensaje para algunos errores genéricos.

El código completo sería:

switch (R1)
    {
    case ERROR_SUCCESS:
        R2 = RegDeleteTree(phkResult, lpSubKey2);
 
        if (R2 == ERROR_SUCCESS)
        {
            MessageBox(NULL, L"Se abrió la clave, y se eliminó el árbol.",
                L"Explorando la API", MB_ICONEXCLAMATION);
        }
        else if (R2 == ERROR_ACCESS_DENIED)
        {
            MessageBox(NULL, L"Se abrió la clave, pero hay acceso denegado.",
                L"Explorando la API", MB_ICONEXCLAMATION);
 
        }
        else if (R2 == ERROR_FILE_NOT_FOUND)
        {
            MessageBox(NULL, L"Se abrió la clave, no se encontró la sub-clave.",
                L"Explorando la API", MB_ICONEXCLAMATION);
        }
        else
        {
            MessageBox(NULL, L"Error eliminando la sub-clave.",
                L"Explorando la API", MB_ICONEXCLAMATION);
        }
 
        break; //Fin del primer case
 
    case ERROR_FILE_NOT_FOUND:
        MessageBox(NULL, L"No se encontró la sub-clave.",
            L"Explorando la API", MB_ICONEXCLAMATION);
        break; //Fin del segundo case
 
    case ERROR_ACCESS_DENIED:
        MessageBox(NULL, L"Error, Acceso Denegado.",
            L"Explorando la API", MB_ICONEXCLAMATION);
        break; //Fin del tercer case
 
    default:
        MessageBox(NULL, L"Error abriendo la sub-clave.",
            L"Explorando la API", MB_ICONEXCLAMATION);
        break; //Fin del último case
 
 
    } //Fin del switch

El mensaje al eliminar la sub-clave con el código anterior se vería así:



Explorando resultados


Después de que la operación sea exitosa, podemos ver fácilmente con Process Monitor cómo Windows realmente la hace:



Windows primero hace la operación de abrir la clave que devuelve phkResult que es HKEY_CURRENT_USER\APrincipal, luego consulta las sub-claves que hay haciendo la operación de RegEnumKey para saber cuántas debe abrir, procede a abrirlas para eliminación, es decir, con acceso Delete y las elimina haciendo la operación de RegDeleteKey. Hace exactamente lo mismo con la sub-clave Borrar, una vez elimina las sub-claves de ésta. Como lo mencioné al principio, de esta misma forma lo habríamos podido hacer, pero la función RegDeleteTree ahorra bastante trabajo.

Ver también:
Explorando la API de Windows en C++: La función RegOpenKeyEx para abrir claves de Registro.
Explorando la API de Windows en C++: Creando mi primera clave de Registro con la función RegCreateKeyEx (es-ES).
Explorando la API de Windows en C++: Mi primera Valor de Registro utilizando las funciones RegCreateKeyEx y RegSetValueEx (es-ES)
Explorando la API de Windows en C++: La función RegDeleteKeyEx para eliminar claves de Registro (es-ES)