Dos funciones Delphi útiles para leer y guardar datos en el Registro de Windows

Accediendo al Registro de Windows

Copyright © 2000 Ernesto De Spirito

Boletín Pascal. Newsletter gratuito para programadores Delphi (y Kylix) con artículos, noticias, trucos, componentes y enlaces a nuevo contenido Delphi en la red.

¿Qué es el Registro de Windows?

Es donde Windows guarda muchas de sus opciones de configuración y también permite a las aplicaciones acceder a estos datos, así como guardar sus propios datos.

Si desea echar un vistazo al registro simplemente ejecute la aplicación REGEDIT.EXE localizada en su directorio de Windows. Tenga cuidado de no cambiar nada o podría terminar arruinado su instalación! Ahora bien, los datos se guardan en el registro en forma de una estructura de árbol. Hay varias raíces (varios árboles):

  HKEY_CLASSES_ROOT
  HKEY_CURRENT_USER
  HKEY_LOCAL_MACHINE
  HKEY_USERS
  HKEY_PERFORMANCE_DATA
  HKEY_CURRENT_CONFIG
  HKEY_DYN_DATA

Cada raíz contiene valores y claves. Los valores son datos guardados bajo nombres de elementos (panel derecho de RegEdit). Las claves pueden tener valores así como otras claves, formando una estructura de árbol (panel izquierdo de RegEdit).

TRegistry

La clase TRegistry está declarada en la unidad Registry, así que tendrá que añadirla a la cláusula uses de la unidad o programa donde quiera usarla. Para acceder a un dato en el registro primero debe crear un objeto de esta clase, asignar la raíz donde se encuentra el dato en la propiedad RootKey (los valores están definidos en la unidad Windows) y luego intentar abrir la clave donde está ese dato con el método OpenKey que devolverá True si tuvo éxito. Lugo puede leer (con las funciones ReadXxxx) o escribir (con los procedimientos WriteXxxx) los valores de la clave abierta y luego de eso, debe cerrar la clave con el método CloseKey. Cuando haya terminado con el registro, debería liberar el objeto creado.

Veamos un ejemplo de cómo obtener el nombre del procesador que posee nuestro ordenador:

uses Registry, Windows, Dialogs;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TRegistry.Create do
    try
      RootKey := HKEY_LOCAL_MACHINE;
      if OpenKey('\Hardware\Description\System'
          + '\CentralProcessor\0', False) then begin
        ShowMessage(ReadString('Identifier'));
        CloseKey;
      end;
    finally
      Free;
    end;
end;

Puede ver otro ejemplo en el artículo Determinando la aplicación asociada

Por supuesto, hay muchas otras cosas que se pueden hacer con el registro, como crear y eliminar claves y valores...

La clase TRegistryIniFile hace fácil a las aplicaciones escribir y leer su información de configuración en y desde el registro, mientras que TRegistry opera a un nivel más bajo.

GetRegistryData

Para simplificar la lectura de valores de datos del registro puede usar la siguiente función capaz de leer cualquier tipo de dato del registro y lo devuelve como un variant (string o integer). La función realiza tratamiento de excepciones.

uses Registry, Windows, SysUtils;

function GetRegistryData(RootKey: HKEY; Key, Value: string): variant;
var
  Reg: TRegistry;
  RegDataType: TRegDataType;
  DataSize, Len: integer;
  s: string;
label cantread;
begin
  Reg := nil;
  try
    Reg := TRegistry.Create(KEY_QUERY_VALUE);
    Reg.RootKey := RootKey;
    if Reg.OpenKeyReadOnly(Key) then begin
      try
        RegDataType := Reg.GetDataType(Value);
        if (RegDataType = rdString) or
           (RegDataType = rdExpandString) then
          Result := Reg.ReadString(Value)
        else if RegDataType = rdInteger then
          Result := Reg.ReadInteger(Value)
        else if RegDataType = rdBinary then begin
          DataSize := Reg.GetDataSize(Value);
          if DataSize = -1 then goto cantread;
          SetLength(s, DataSize);
          Len := Reg.ReadBinaryData(Value, PChar(s)^, DataSize);
          if Len <> DataSize then goto cantread;
          Result := s;
        end else
cantread:
          raise Exception.Create(SysErrorMessage(ERROR_CANTREAD));
      except
        s := ''; // Deallocates memory if allocated
        Reg.CloseKey;
        raise;
      end;
      Reg.CloseKey;
    end else
      raise Exception.Create(SysErrorMessage(GetLastError));
  except
    Reg.Free;
    raise;
  end;
  Reg.Free;
end;

Llamada de ejemplo

ShowMessage(GetRegistryData(HKEY_LOCAL_MACHINE,
  '\Hardware\Description\System\CentralProcessor\0', 'Identifier'));

SetRegistryData

Para simplificar la escritura de un valor de datos en el registro puede usar el siguiente procedimiento capaz de escribir cualquier tipo de datos en el registro. El procedimiento tratamiento de excepciones.

uses Registry, Windows, SysUtils;

procedure SetRegistryData(RootKey: HKEY; Key, Value: string;
  RegDataType: TRegDataType; Data: variant);
var
  Reg: TRegistry;
  s: string;
begin
  Reg := TRegistry.Create(KEY_WRITE);
  try
    Reg.RootKey := RootKey;
    if Reg.OpenKey(Key, True) then begin
      try
        if RegDataType = rdUnknown then
          RegDataType := Reg.GetDataType(Value);
        if RegDataType = rdString then
          Reg.WriteString(Value, Data)
        else if RegDataType = rdExpandString then
          Reg.WriteExpandString(Value, Data)
        else if RegDataType = rdInteger then
          Reg.WriteInteger(Value, Data)
        else if RegDataType = rdBinary then begin
          s := Data;
          Reg.WriteBinaryData(Value, PChar(s)^, Length(s));
        end else
          raise Exception.Create(SysErrorMessage(ERROR_CANTWRITE));
      except
        Reg.CloseKey;
        raise;
      end;
      Reg.CloseKey;
    end else
      raise Exception.Create(SysErrorMessage(GetLastError));
  finally
    Reg.Free;
  end;
end;

Llamada de ejemplo

SetRegistryData(HKEY_LOCAL_MACHINE,
  '\Software\Microsoft\Windows\CurrentVersion',
  'RegisteredOrganization', rdString, 'Latium Software');
JfControls Library - para Delphi y C++ Builder