Использование реестра
01.01.2007
Алексей Федоров
Реестр - это центральное хранилище информации о параметрах системы и установленных программах. В версиях Windows до Windows 95 программисты сохраняли параметры программ либо в INI-файлах WIN.INI и SYSTEM.INI, либо в дополнительных INI-файлах. Хотя использование INI-файлов поддерживается и в Win32, Microsoft настоятельно рекомендует для хранения необходимых в работе программы параметров пользоваться реестром. Реестр представляет собой иерархическую базу данных, cостоящую из секций, подсекций и элементов. Каждая секция имеет свое назначение. Хранить данные о пользовательских программах Microsoft рекомендует в секции HKEY_CURRENT_USER и подсекции Software. В этой подсекции вы создаете подсекцию, идентифицирующую вашу программу или фирму, и уже внутри нее располагаете данные.
Модуль Registry
Для упрощения работы с регистратором в состав Delphi (начиная с версии 2.0) входит модуль REGISTRY, содержащий реализацию трех классов, - TRegistry, TRegistryIniFile и TRegIniFile.
Внимание! Чтобы использовать свойства и методы классов TRegistry, TRegistryIniFile и TRegIniFile, необходимо включить в список uses модуль Registry.
TRegIniFile
Собственно говоря, задача класса TRegIniFile - упростить перенос 16-битных программ в среду Windows 95. Методы этого класса эквивалентны методам класса TIniFile в 16-битной версии Delphi. Класс TRegIniFile позволяет обращаться к секции HKEY_CURRENT_USER, считывать и записывать строки (методы ReadString и WriteString), целочисленные значения (методы ReadInteger и WriteInteger), логические значения (методы ReadBool и WriteBool), секции (методы ReadSection, ReadSections и ReadSectionValues), удалять секции (метод EraseSection) и элементы (метод DeleteKey). Рассмотрим на примерах, как используются функции этого класса.
Microsoft рекомендует записывать данные, относящиеся к вашей программе, в подсекции секции HKEY_CURRENT_USER_Software. Предположим (не особенно фантазируя на эту тему), что ваша программа называется RegDemo, и данные для нее располагаются в секции Software\RegDemo. Ниже мы покажем, как поместить в регистратор строчные, целочисленные и логические данные, а затем считать их, - этих операций будет достаточно для того, чтобы сохранить в регистраторе параметры нашей программы, а затем считать их.
Прежде чем записать данные в определенную секцию, ее необходимо создать. Это происходит при вызове конструктора объекта TRegIniFile. В качестве параметра вы указываете название секции, и если таковой не существует, она создается:
RegFile := TRegIniFile.Create(SubKey);
После того как файл регистратора открыт (и создана определенная секция), мы можем записать данные. Поддерживаются три типа данных: целочисленные, логические и строчные данные. Для записи этих данных существуют методы WriteInteger, WriteBool и WriteString. В качестве параметров указываются:
- название подсекции;
- название элемента;
- записываемые данные.
Так, чтобы записать значение элемента MyIntVal в подсекции IntKey, следует выполнить код
RegFile.WriteInteger(IntKey, 'Int_Val', 32000);
а для того чтобы прочесть значение, необходимо вызвать метод ReadInteger (в качестве параметров указываются название подсекции, название элемента и значение по умолчанию):
RegFile.ReadInteger(IntKey, 'Int_Val', 0));
Для чтения логических и строчных данных используются соответственно методы ReadBool и ReadStr, а для их записи - методы WriteBool и WriteString.
Расссмотрим пример использования перечисленных выше методов класса TRegIniFile. Расположим в форме компонент Memo, две группы GroupBox и шесть кнопок - три в группе Write и три в группе Read. Нажатие каждой кнопки в группе Write приведет к записи соответствующего значения в реестр, нажатие каждой кнопки в группе Read - к чтению этого значения.
Ниже приведен исходный текст модуля, в котором содержатся обработчики нажатия кнопок, использующие методы класса TRegIniFile.
unit RDUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Registry;
type
TForm1 = class(TForm)
Memo1: TMemo;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
Label1: TLabel;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation{$R *.DFM}var
RegFile: TRegIniFile;
const
//Подсекция
SubKey: string = 'Software\RegDemo';
// Элемент для хранения логических данных
BoolKey: string = 'BoolKey';
// Элемент для хранения целочисленных данных
IntKey: string = 'IntKey';
// Элемент для хранения строчных данных
StrKey: string = 'StrKey';
procedure TForm1.FormCreate(Sender: TObject);
begin
// Создать экземпляр класса
RegFile := TRegIniFile.Create(SubKey);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Записать целочисленное значение
RegFile.WriteInteger(IntKey, 'Value', 1998);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// Записать булево значение
RegFile.WriteBool(BoolKey, 'Value', True);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
// Записать строку
RegFile.WriteString(StrKey, 'Value', 'Demo');
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
// Считать целочисленное значение
Memo1.Lines.Add('Int Value = ' +
IntToStr(RegFile.ReadInteger(IntKey, 'Value', 0)));
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
// Считать булево значение
if RegFile.ReadBool(BoolKey, 'Value', False) then
Memo1.Lines.Add('Bool Value = True')
else
Memo1.Lines.Add('Bool Value = False');
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
// Считать строку
Memo1.Lines.Add(RegFile.ReadString(StrKey, 'Value', ''));
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// Удалить секцию
RegFile.EraseSection(SubKey);
// Освободить память
RegFile.Free;
end;
end.
На приведенном ниже рисунке показано, как выглядит созданная нами подсекция в редакторе REGEDIT.
Отметим, что рассмотренных выше функций вполне достаточно для того чтобы обеспечить минимальную функциональность приложения. Если же вам требуется читать и записывать данные из других секций реестра, вы можете воспользоваться методами класса TRegistry или (что мене удобно) непосредственно функциями Win32 API.
Класс TRegistry
Прежде чем рассмотреть пример использования свойств и методов класса TRegistry, давайте кратко перечислим их.
В следующей таблице перечислены свойства класса TRegistry.
+-------------+-----------------------------------+
| Свойство | Описание |
+-------------+-----------------------------------+
| CurrentKey | Позволяет узнать текущую |
| | подсекцию, в которой проводятся |
| | операции по чтению и записи. Для |
| | изменения подсекции следует |
| | использовать методы OpenKey и |
| | OpenKeyReadOnly |
+-------------+-----------------------------------+
| CurrentPath | Позволяет узнать полное название |
| | текущей подсекции |
+-------------+-----------------------------------+
| LazyWrite | Задает способ обновления |
| | информации в реестре - |
| | непосредственно или после вызова |
| | метода CloseKey. |
+-------------+-----------------------------------+
| RootKey | Задает корневую секцию в реестре. |
| | По умолчанию установлено значение |
| | HKEY_CURRENT_USER |
+-------------+-----------------------------------+
В следующей таблице перечислены методы класса TRegistry.
+-------------------+-----------------------------------+
| Метод | Описание |
+-------------------+-----------------------------------+
| CloseKey | Записывает внесенные изменения и |
| | закрывает текущую подсекцию |
+-------------------+-----------------------------------+
| Create | Создает экземпляр класса |
| | TRegistry и задает значение |
| | корневой секции - |
| | HKEY_CURRENT_USER |
+-------------------+-----------------------------------+
| CreateKey | Создает подсекцию |
+-------------------+-----------------------------------+
| DeleteKey | Удаляет подсекцию |
+-------------------+-----------------------------------+
| DeleteValue | Удаляет значение элемента |
+-------------------+-----------------------------------+
| Destroy | Уничтожает ранее созданный |
| | экземпляр класса TRegistry |
+-------------------+-----------------------------------+
| GetDataInfo | Возвращает тип данных для |
| | указанного элемента |
+-------------------+-----------------------------------+
| GetDataSize | Возвращает размер данных для |
| | указанного элемента |
+-------------------+-----------------------------------+
| GetDataType | Возвращает тип данных для |
| | указанного элемента |
+-------------------+-----------------------------------+
| GetKeyInfo | Возвращает информацию о текущем |
| | элементе |
+-------------------+-----------------------------------+
| GetKeyNames | Возвращает имена подсекций для |
| | указанной секции |
+-------------------+-----------------------------------+
| GetValueNames | Возвращает названия элементов для |
| | указанной подсекции |
+-------------------+-----------------------------------+
| HasSubKeys | Позволяет узнать, имеются ли |
| | подсекции для указанной секции |
+-------------------+-----------------------------------+
| KeyExists | Позволяет узнать, существует ли |
| | элемент |
+-------------------+-----------------------------------+
| LoadKey | Создает новую подсекцию и |
| | загружает в нее информацию из |
| | указанного файла |
+-------------------+-----------------------------------+
| MoveKey | Перемещает указанную подсекцию и |
| | все вложенные подсекции в |
| | заданное место |
+-------------------+-----------------------------------+
| OpenKey | Открывает подсекцию |
+-------------------+-----------------------------------+
| OpenKeyReadOnly | Открывает подсекцию только для |
| | чтения |
+-------------------+-----------------------------------+
| ReadBinaryData | Считывает данные в бинарном |
| | формате |
+-------------------+-----------------------------------+
| ReadBool | Считывает данные в булевом |
| | формате |
+-------------------+-----------------------------------+
| ReadCurrency | Считывает данные в формате валюты |
+-------------------+-----------------------------------+
| ReadDate | Считывает данные в формате даты |
+-------------------+-----------------------------------+
| ReadDateTime | Считывает данные в формате |
| | "дата/время" |
+-------------------+-----------------------------------+
| ReadFloat | Считывает данные в формате с |
| | плавающей точкой |
+-------------------+-----------------------------------+
| ReadInteger | Считывает данные в целочисленном |
| | формате |
+-------------------+-----------------------------------+
| ReadString | Считывает данные в строчном |
| | формате |
+-------------------+-----------------------------------+
| ReadTime | Считывает данные в формате |
| | времени |
+-------------------+-----------------------------------+
| RegistryConnect | Устанавливает соединение с |
| | реестром на другом компьютере |
+-------------------+-----------------------------------+
| RenameValue | Переименовывает элемент |
+-------------------+-----------------------------------+
| ReplaceKey | Замещает значение элемента |
| | значениями из файла |
+-------------------+-----------------------------------+
| RestoreKey | Восстанавливает значение элемента |
| | из файла |
+-------------------+-----------------------------------+
| SaveKey | Сохраняет значение элемента в |
| | файле |
+-------------------+-----------------------------------+
| UnLoadKey | Удаляет подсекцию, загруженную |
| | методом LoadKey |
+-------------------+-----------------------------------+
| ValueExists | Позволяет узнать, существует ли |
| | значение у элемента |
+-------------------+-----------------------------------+
| WriteBinaryData | Записывает данные в бинарном |
| | формате |
+-------------------+-----------------------------------+
| WriteBool | Записывает данные в булевом |
| | формате |
+-------------------+-----------------------------------+
| WriteCurrency | Записывает данные в формате |
| | валюты |
+-------------------+-----------------------------------+
| WriteDate | Записывает данные в формате даты |
+-------------------+-----------------------------------+
| WriteDateTime | Записывает данные в формате |
| | "дата/время" |
+-------------------+-----------------------------------+
| WriteExpandString | Записывает данные в формате |
| | "расширенной" строки |
+-------------------+-----------------------------------+
| WriteFloat | Записывает данные в формате с |
| | плавающей точкой |
+-------------------+-----------------------------------+
| WriteInteger | Записывает данные в целочисленном |
| | формате |
+-------------------+-----------------------------------+
| WriteString | Записывает данные в строчном |
| | формате |
+-------------------+-----------------------------------+
| WriteTime | Записывает данные в формате |
| | времени |
+-------------------+-----------------------------------+
После того как мы кратко познакомились со свойствами и методами класса TRegistry, давайте рассмотрим несколько примеров их использования.
Инициализация
Перед использованием свойств и методов класса TRegistry, необходимо создать экземпляр этого класса. Например:
var
R: TRegistry;
...
R := TRegistry.Create;
Задание корневой секции
Если вы собираетесь работать с секцией, отличной от HKEY_CURRENT_USER (это значение задается по умолчанию), то после инициализации вы должны изменить значение свойства RootKey.
Возможны следующие значения:
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_PERFORMANCE_DATA
HKEY_CURRENT_CONFIG
HKEY_DYN_DATA
Например:
with R do
begin
RootKey := HKEY_LOCAL_MACHINE;
//
// Продолжаем работу с реестром
//
end;

