Работа с реестром в Delphi

Работа с реестром в Delphi

Еще в Windows 3.1 программы сохраняли свои настройки в файлах с расширением .ini. Однако с появлением Windows 95 и более поздних версий все больше и больше программ стали использовать реестр Windows для записи своих настроек. Реестр Windows стал общей базой данных с настройками всех установленных программ. Но помимо того, что это удобное место для хранения необходимой программе информации, реестр также содержит настройки самой Windows, и поэтому работа с ним обязательна, если вы хотите, чтобы ваше приложение интегрировалось с операционной системой. Простейшим примером этого является тот факт, что реестр записывает, какие файлы открываются с помощью какой программы, и если вы хотите открыть его двойным щелчком по созданному вашей программой документу, вам необходимо добавить соответствующую запись реестра. Обычно это делается во время установки программы, но если вы создали программу для работы с широко используемым форматом файла (например, .html), то рекомендуется дать пользователям возможность ассоциировать их с вашей программой из самой программы. — в противном случае установка другого HTML-редактора, например, может переопределить программу по умолчанию для открытия HTML-документов и вынудить пользователя переустановить ваш продукт, чтобы вернуть настройки в то состояние, в котором они должны быть. Реестр еще более важен, если вы пишете системное программное обеспечение. К счастью, Borland максимально упростила работу с реестром, предоставив класс TRegistry. В этой статье мы рассмотрим свойства и методы этого класса.

Однако прежде чем мы начнем, я хочу отметить, что TRegistry — не единственный класс, обеспечивающий доступ к реестру. В Delphi также есть класс TRegistryIniFile, который скрывает реестр и позволяет сохранять настройки вашей программы так же, как в INI-файле. Кроме того, этот класс позволяет перейти от использования INI-файлов к использованию реестра Windows с минимальным изменением кода — достаточно изменить имя класса TIniFile на TRegistryIniFile. Не буду подробно останавливаться на этом классе — здесь цель — полноценная работа с реестром, а не имитация работы с INI-файлами, что предназначено просто для удобства разработчиков.

Давайте познакомимся с реестром — наверное, каждый из вас его видел и знает, что это такое, но я все же скажу о нем несколько слов. Информация выстроена в иерархическую структуру, имеющую несколько начальных ключей — HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CURRENT_CONFIG. Если вы запускали RegEdit, вы знаете, что слева у вас есть список «каталогов», а справа список всех значений в текущем «каталоге». На самом деле эти «каталоги» называются ключами. Каждый ключ может иметь неограниченное количество подразделов, которые, в свою очередь, могут иметь подразделы и т. д. Каждый ключ также может содержать неограниченное количество переменных. Существует несколько типов данных. Для вас это не принципиально, так как Delphi (а точнее класс TRegistry) предоставляет методы для чтения и записи данных в известных вам типах — Integer, String и т.д.

Чтобы использовать класс TRegistry, вы должны добавить Registry в раздел Uses приложения.

Когда вы создаете объект TRegistry, вы назначаете ему домашний ключ, который является одним из домашних ключей, перечисленных ранее — по умолчанию это HKEY_CURRENT_USER. Позже вы можете изменить первоначальный ключ. Оттуда вы работаете с подразделами этого начального ключа и записанными в них переменными. Конечно, первое, что вам нужно сделать, это создать объект TRegistry. В зависимости от потребностей вашей программы этот объект может быть создан при создании формы или по какому-то определенному событию. Мы будем использовать создание формы. В TRegistry есть два предопределенных конструктора: вы можете вызвать конструктор без параметров или с одним параметром, инициализирующим свойство Access заданным значением. Access определяет права программы, когда она открывает ключи — может ли она создавать подразделы, изменять значения переменных и т. д. По умолчанию (если вызвать конструктор без параметра) программа имеет полный доступ к реестру. Позже вы можете изменить это с помощью свойства Access. Вот как будет выглядеть код нашего приложения:

Код:


unit Unit1; 

interface 

uses 
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Registry; 

type 
TForm1 = class(TForm) 
procedure FormCreate(Sender: TObject); 
private 
{ Private declarations } 
public 
{ Public declarations } 
end; 

var 
Form1: TForm1; 
RegEdit: TRegistry; 
implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
RegEdit:=TRegistry.Create; 
end; 

end. 

Характеристики:

Класс TRegistry имеет всего 5 свойств. О первом из них мы уже упоминали — Access. Он может иметь следующие значения:
KEY_ALL_ACCESS представляет собой комбинацию KEY_READ, KEY_WRITE а также KEY_CREATE_LINK.
KEY_READ представляет собой комбинацию KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYSа также KEY_NOTIFY.
KEY_WRITE представляет собой комбинацию KEY_SET_VALUE а также KEY_CREATE_SUB_KEY.
KEY_QUERY_VALUE позволяет приложению читать значения переменных данного ключа.
KEY_ENUMERATE_SUB_KEYS разрешает приложению читать имена подразделов.
KEY_NOTIFY позволяет приложению получать уведомления при внесении изменений в реестр.
KEY_SET_VALUE позволяет приложению изменять переменные в данном ключе.
KEY_CREATE_SUB_KEY позволяет приложению создавать подразделы.
KEY_CREATE_LINK разрешает приложению создавать соединения.
KEY_EXECUTE ограничивает доступ к значениям только для чтения.

Значение свойства Access используется при открытии ключей, но не при их создании. Вы можете комбинировать несколько значений с помощью оператора ИЛИ. Обратите внимание, что это права, которые приложение будет запрашивать у Windows, а не права, которыми оно действительно будет обладать. Поэтому, если ваше приложение требует больше прав на реестр, чем ему дает Windows, оно может работать некорректно (или вообще не работать). Поэтому никогда не просите больше прав, чем вам нужно.

Другое свойство TRegistry — CurrentKey. Он содержит ключ, открытый приложением в данный момент. Любые операции, которые вы выполняете, выполняются с текущим ключом. Вы можете открыть другой ключ любым из методов TRegistry, которые мы рассмотрим далее.
CurrentPath — это строка, содержащая полный путь от начала до текущего ключа включительно.
LazyWrite — это логическое свойство, которое указывает, как изменения записываются в реестр. При создании объекта TRegistry это свойство инициализируется значением true. Если его значение равно true, изменения сохраняются при закрытии ключа, но метод CloseKey может вернуть управление приложению до их сохранения. Если false, то CloseKey возвращает управление приложению только после сохранения изменений, поэтому изменения должны быть сохранены, прежде чем приложение сможет выполнять любую другую операцию. Этот метод обеспечивает запись изменений, но значительно медленнее, чем использование истинного значения для свойства LazyWrite.
RootKey содержит начальный ключ. По умолчанию это HKEY_CURRENT_USER, но вы можете изменить его, изменив значение свойства RootKey.

Несмотря на небольшое количество свойств, TRegistry предоставляет большое количество методов. Многие из них относятся к чтению и записи значений, поскольку класс предоставляет отдельные методы для чтения и записи разных типов данных.
OpenKey открывает выбранный ключ. Он принимает два аргумента: первый представляет собой строку, содержащую запрошенный ключ, а второй, который может быть истинным или ложным, определяет, создавать ли ключ, если выбранный ключ не существует. При вызове метода свойство CurrentKey принимает в качестве значения открытый или созданный ключ. Если ключ имеет значение nil, то корневой ключ, указанный свойством RootKey, становится текущим. Обратите внимание, что для значения необходимо указать полный путь к ключу (исключая начальный ключ), поэтому строка должна начинаться с символа ‘.
OpenKeyReadOnly также открывает ключ, но также устанавливает значение KEY_READ для свойства Access. Еще одно существенное отличие от предыдущего метода заключается в том, что OpenKeyReadOnly не принимает второй аргумент — он никогда не создает ключ, если ключ, указанный в первом (и единственном) аргументе метода, не существует.
CloseKey закрывает текущий ключ. Изменения, внесенные в реестр, сохраняются при закрытии ключа, поэтому не следует держать ключи открытыми дольше, чем это необходимо. Этот метод не принимает аргументов.
CreateKey создает ключ. Он принимает один аргумент — строку, указывающую имя создаваемого ключа. CreateKey всегда использует значение KEY_ALL_ACCESS свойства Access.
DeleteKey удаляет ключ, указанный переданным аргументом.
KeyExist — это логическая функция, которая принимает строковый аргумент и возвращает информацию о том, существует ли ключ с таким именем.
HasSubKeys возвращает значение true, если текущий ключ содержит подразделы.
GetKeyNames принимает в качестве своего единственного аргумента переменную типа TStrings и возвращает в ней имена всех подразделов текущего ключа,
GetValueNames тоже принимает в качестве аргумента переменную типа TStrings, но возвращает в ней имена всех переменных в текущем ключе.

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

Существует три метода, которые предоставляют информацию о типе данных, содержащихся в данной переменной. Все три принимают имя переменной в качестве первого аргумента, но возвращают о ней разную информацию:
GetDataSize возвращает размер информации (в байтах), содержащейся в переменной.
GetDataType возвращает тип данных в переменной. Возвращаемое значение может быть:
rdUnknown Значение имеет неопределенный тип.
rdString Значение представляет собой строку символов.
rdExpandString Значение представляет собой строку символов, содержащую ссылки на так называемые переменные окружения (environment в переводе с английского означает «окружение». Переменные окружения — это системные переменные. Например, переменная %WINDIR% содержит каталог, в котором установлена ​​Windows).
rdInteger Значение представляет собой число
rdBinary Двоичное значение
GetDataInfo также принимает второй аргумент — переменную типа TRegDataInfo, в которой также возвращает информацию о запрошенной переменной. TRegDataInfo — это запись с двумя полями. Первый из них, RegData, содержит тип данных — тот же, что и GetDataType. Второй — DataSize, содержит размер в байтах информации. На практике этот метод объединяет два предыдущих.

Ниже приведены несколько методов Read* и соответствующие им методы Write*, которые считывают и записывают значения регистров, единственная разница между которыми заключается в используемом типе данных.

ReadBool, ReadCurrency, ReadDate, ReadDateTime, ReadFloat, ReadInteger, ReadString и ReadTime принимают имя переменной в качестве аргумента и возвращают ее значение как соответствующий тип данных. Соответствующие методы Write* (WriteBool, WriteCurrency, WriteDate, WriteDateTime, WriteFloat, WriteInteger, WriteString и WriteTime) принимают в качестве первого аргумента имя переменной, а в качестве второго — ее значение как соответствующий тип данных и записывают их в регистр.

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

Что еще более важно, Windows, Internet Explorer и многие другие приложения могут управляться реестром. Если знать его структуру, если знать, где что написано и где что нужно изменить, можно добавлять и удалять пункты из контекстного меню, менять настройки Windows — в том числе недоступные вне самого реестра, добавлять кнопки интернета Explorer, для модификации MS Office… В общем, для интеграции ваших приложений с продуктами Microsoft

Автор: Максим Крижановский

Поделиться в соцсетях