Accessing the Windows Registry

This article introduces a couple of handy functions that make it easy to read and write values in the Windows Registry.

WHAT IS THE REGISTRY?

It is where Windows stores many of its configuration options and also allows applications to access this data as well as save their own data.



If you want to take a look at the registry, just execute the REGEDIT.EXE application located in the Windows directory. Be careful not to change anything or you could end up ruining your installation!



Now, the data in the registry is stored in a tree structure. There are many roots (many trees):



HKEY_CLASSES_ROOT

  HKEY_CURRENT_USER

  HKEY_LOCAL_MACHINE

  HKEY_USERS

  HKEY_PERFORMANCE_DATA

  HKEY_CURRENT_CONFIG

  HKEY_DYN_DATA




Each root can have values and keys. The values are data stored under item names (right panel of RegEdit). Keys can have values and other keys, forming a tree structure (left panel of RegEdit).



TREGISTRY

The TRegistry class is declared in the Registry unit, so you will have to add this unit to the uses clause of the unit or program where you want to use it. To access a value in the registry first you should create an object of this class, assign the root to its RootKey property (the values are defined in the Windows unit) and then try to open a key with the OpenKey function method, which will return True if successful. Then you can read (with the ReadXxxx functions) or write (with the WriteXxxx procedures) the values of the open key and, after that, you should close the key with CloseKey.



When you are done with the registry, you should free the registry object you created.



Let's see an example of how to obtain the name of the processor in our computer:



uses Registry, Windows, Dialogs;



  procedure TForm1.Button1Click(Sender: TObject);

  var

    Reg: TRegistry;

  begin

    Reg := TRegistry.Create;

    Reg.RootKey := HKEY_LOCAL_MACHINE;

      if Reg.OpenKey('\Hardware\Description\System'

        + '\CentralProcessor\0', False) then begin

      ShowMessage(Reg.ReadString('Identifier'));

      Reg.CloseKey;

    end; // if

    Reg.Free;

  end;




You can see another example in the article Determining the associated application.



Of course, there are many more things you can do with the registry, like creating and deleting keys and values...



The TRegistryIniFile class makes it simpler for applications to write and read their configuration information to and from the registry, while TRegistry operates at a lower level.





GETREGISTRYDATA

To simplify reading a data value from the registry you can use the following function that can read any data type from the registry and returns it as a variant (string or integer). The function performs exception handling.



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;

  except

    Reg.Free;

    raise;

  end;




SAMPLE CALL

ShowMessage(GetRegistryData(HKEY_LOCAL_MACHINE,

    '\Hardware\Description\System\CentralProcessor\0', 'Identifier'));




SETREGISTRYDATA

To simplify writing a data value to the registry you can use the following procedure that can write any data type to the registry.



The procedure performs exception handling.



uses Registry, Windows, SysUtils;



  procedure SetRegistryData(RootKey: HKEY; Key, Value: string;

    RegDataType: TRegDataType; Data: variant);

  var

    Reg: TRegistry;

    s: string;

  begin

    Reg := nil;

    try

      Reg := TRegistry.Create(KEY_WRITE);

      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));

    except

      Reg.Free;

      raise;

    end;

    Reg.Free;

  end;




SAMPLE CALL

SetRegistryData(HKEY_LOCAL_MACHINE,

    '\Software\Microsoft\Windows\CurrentVersion',

    'RegisteredOrganization', rdString, 'Latium Software');

 

Share this article!

Follow us!

Find more helpful articles: