(C) Зайцев Олег 1998-2000 |
Программирование на Delphi
|
Система | Реестр | Графика | Сети | Мультимедиа | WEB | Разработка_компонент | Железо | Прочее |
РеестрЭтот раздел посвящен реестру и INI файлам. Он содержит подробную теоретическую информацию и ряд практических примеров Внимание !! Сайт переехал - он теперь расположен по адресу http://z-oleg.com/delphi, размещенные там материалы переработаны и дополнены. На z-ol.chat.ru остается копия, однако обновляться она больше не будет |
|
Работа с реестром в Delphi 1 | D1 | * |
{ Создаем список всех подразделов указанного раздела } procedure TForm1.Button1Click(Sender: TObject); var MyKey : HKey; { Handle для работы с разделом } Buffer : array[0..1000] of char; { Буфер } Err, { Код ошибки } index : longint; { Индекс подраздела } begin Err:=RegOpenKey(HKEY_CLASSES_ROOT,'DelphiUnit',MyKey); { Открыли раздел } if Err<> ERROR_SUCCESS then begin MessageDlg('Нет такого раздела !!',mtError,[mbOk],0); exit; end; index:=0; {Определили имя первого подраздела } Err:=RegEnumKey(MyKey,index,Buffer,Sizeof(Buffer)); while err=ERROR_SUCCESS do { Цикл, пока есть подразделы } begin memo1.lines.add(StrPas(Buffer)); { Добавим имя подраздела в список } inc(index); { Увеличим номер подраздела } Err:=RegEnumKey(MyKey,index,Buffer,Sizeof(Buffer)); { Запрос } end; RegCloseKey(MyKey); { Закрыли подраздел } end;
Задать вопрос | Наверх |
Работа с реестром в Delphi 2+ | D2+ | * |
В Delphi 4 для работы с реестром имеется класс TRegistry. В отличии от своего "младшего брата" (TRegistry в Delphi 1) он может работать со всеми ключами реестра, а не только с HKEY_CLASSES_ROOT.
Рассмотрим работу с TRegistry по шагам.
Если опустить пункт 4, то рабочий минимум
сводится к приведенному ниже коду
var
REG : TRegistry;
begin
REG := TRegistry.Create;
REG.Destroy;
end;
Далее необходимо рассмотреть (вкратце) основные свойства и методы TRegistry
Свойства
Свойства |
Назначение |
property RootKey: HKEY; |
Самое полезное свойство.
Допускает чтение и запись. Определяет корневой
ключ реестра. Допустимые значения: |
property CurrentPath: String; | Путь к текущему ключу |
property LazyWrite: Boolean; | "Ленивая запись". По умолчанию = true, что означает, что на момент возврата из функции закрытия ключа не гарантируется, что изменения в нем записаны в реестр. Если false, то на момент возврата из функции закрытия ключа гарантируется, что все изменения уже записаны в реестр. |
property CurrentKey: HKEY; | Открытый в настоящее время ключ реестра |
Методы
Procedure CloseKey;
Закрывает открытый в данный момент ключ реестра
и записывает в реестра все изменения (если
таковые были), произведенные в данном ключе.
Вызов CloseKey несколько раз или при отсутствии
открытого ключа не вызывает ошибки.
function CreateKey(const Key: String): Boolean;
Создает ключ Key (где Key - путь с разделителями "\",
например Software\Test. Имя корневого ключа в пути не
указывается !! Он задается через property RootKey.
Возвращает True при успешном создании.
function DeleteKey(const Key: String): Boolean;
Удалить ключ Key (аналогично CreateKey, только с
точностью до наоборот)
function DeleteValue(const Name: String): Boolean;
Удалить параметр с именем Name текущего ключа.
Очевидно, что предварительно необходимо открыть
этот ключ.
function GetDataInfo(const ValueName: String; var Value: TRegDataInfo): Boolean;
Получить информацию о параметре ValueName текущего
ключа - его тип и размер. При написании программ
применяется редко, т.к. программист и сам знает,
какого типа его параметры. А вот при написании
разного рода утилит для просмотра и
редактирования реестра он просто незаменим.
Типы:
TRegDataType = (rdUnknown, rdString, rdExpandString, rdInteger, rdBinary);
TRegDataInfo = record
RegData: TRegDataType; // Тип ключа
DataSize: Integer; // Размер данных
end;
Данная функция возвращает комплексную информацию о параметре, для получения данных о размере или типе можно применять GetDataSize и GetDataType
function GetDataSize(const ValueName: String): Integer;
Получить размер параметра ValueName текущего ключа в
байтах. Если - при ошибке. Для строкового
параметра размер учитывает в размере и один байт
для #0, завершающего строку .
function GetDataType(const ValueName: String): TRegDataType;
Получить тип текущего ключа.
function GetKeyInfo(var Value: TRegKeyInfo): Boolean;
Получить информацию о ключе. Возвращает
заполненную структуру:
TRegKeyInfo = record MaxSubKeyLen: Integer; // Количество подключей NumValues: Integer; // Количество параметров MaxValueLen: Integer; // Максимальная длина имени параметра MaxDataLen: Integer; // Максимальная длина данных FileTime: TFileTime; // Время последней записи ключа end;
Как очевидно из структуры, она предназначена для построения программ просмотра реестра. При успешном выполнении возвращает true.
procedure GetKeyNames(Strings: TStrings);
Заполняет указанный Strings списком под ключей
текущего ключа. Применяется для построения
программ просмотра реестра или в том случае,
когда количество подключей неизвестно. Например,
одна из моих программ создает в одном из ключей
несколько подключей с одинаковой структурой, но
их количество заранее неизвестно (настройки
пользователей).
procedure GetValueNames(Strings: TStrings);
Заполняет указанный Strings списком параметров
текущего ключа.
function HasSubKeys: Boolean;
Возвращает True, если текущий ключ имеет подключи и
False в противном случае
function KeyExists(const Key: String): Boolean;
Возвращает True, если ключ Key существует. Полезная
функция, рекомендуется применять ее перед
открытием ключей.
function LoadKey(const Key, FileName: String): Boolean;
Создает ключ Key и загружает в него данные из файла
с именем FileName. Полезно при написании
инсталляторов. Возвращает True при успешном
выполнении.
procedure MoveKey(const OldName, NewName: String; Delete: Boolean);
Копировать или переименовать ключ. В любом
случае копирует все из ключа OldName в NewName (со всеми
подключами). После копирования анализируется
Delete, и если он true, то ключ OldName уничтожается со
всем содержимым. Лично у меня не было потребности
в применении данной функции - она не требуется
программ и предначначена для построения
редакторов реестра.
function OpenKey(const Key: String; CanCreate: Boolean): Boolean;
Очень важная функция - с нее начинается работа с
ключом. Key - имя открываемого ключа. Если ключ с
указанным именем не найден и CanCreate=true, то
производится попытка создать ключ с указанным
именем. Возвращает признак успешности открытия
ключа, его обязательно следует анализировать.
function OpenKeyReadOnly(const Key: String): Boolean;
Тоже, что и OpenKey, но открытие идет в режиме
"только чтение"
Внимание !!!!!! Все функции типа Read** при вызове генерируют исключение, если параметр не найден. Это исключение следует отлавливать при помощи try except или проверять наличие параметра при помощи ValueExists перед его чтением.
function ReadBinaryData(const Name: String; var Buffer; BufSize: Integer): Integer;
Читает значение параметра с именем Name текущего
(открытого) ключа в Buffer размером BufSize.
function ReadBool(const Name: String): Boolean;
Считать значение параметра с именем Name типа Boolean
function ReadDate(const Name: String): TDateTime;
Считать значение параметра с именем Name типа дата
function ReadDateTime(const Name: String): TDateTime;
Считать значение параметра с именем Name типа
дата-время
function ReadTime(const Name: String): TDateTime;
Считать значение параметра с именем Name типа
время
function ReadFloat(const Name: String): Double;
Считать значение параметра с именем Name типа Double
function ReadInteger(const Name: String): Integer;
Считать значение параметра с именем Name типа Integer
function ReadString(const Name: String): String;
Считать значение параметра с именем Name типа String
function RegistryConnect(const UNCName: String): Boolean;
Подключить сетевой реестр машины UNCName (формат:
\\сетевое имя машины). Перед вызовом этой функции
программа должна установить RootKey в значение
HKEY_USERS или HKEY_LOCAL_MACHINE. При успешном соединении и
открытии удаленного реестра его RootKey ставится в
заданное перед вызовам значение свойства RootKey и
возвращается True.
procedure RenameValue(const OldName, NewName: String);
Переименовать параметр текущего ключа с именем
OldName в NewName.
function ReplaceKey(const Key, FileName, BackUpFileName: String): Boolean;
Заменить место хранения ключа. Обычно ключи
хранятся в базовом файле реестра, нот вызовом
данной функции можно задать в качестве места
хранения ключа отдельный файл с именем FileName (его
следует предварительно создать при помощи savekey).
При каждой перезагрузке компьютера ключ Key будет
загружаться значениями, считываемыми из файла
этого файла FileName,т.е. по сути мы имеет дело с ульем
(hive) в терминологии Windows NT. Определение: Улей -
часть реестра (его ячейка). Улей является
дискретным набором ключей, подключей и
параметров, который находится вверху иерархии
реестра. Улей поддерживается одиночным файлом.
BackUpFileName - имя резервной копии, которая создается
перед перезаписью данных ключа Key. Если кого
интересуют подробности, то следует почитать
книгу по реестру Windows NT, главы типа "Ульи и
файлы" и "Целостность и восстановление улья в
реестре". При разработке практических
приложений я не разу не применял этот вызов.
function RestoreKey(const Key, FileName: String): Boolean;
Открывает указанный ключ и перезаписывает его
данные и подключи данными из файла FileName.
function SaveKey(const Key, FileName: String): Boolean;
Сохраняет все параметры указанного ключа и всех
его подключей в файле FileName. Может применяться
совместно с LoadKey и RestoreKey для создания и
восстановления ключей реестра.
function UnLoadKey(const Key: String): Boolean;
Удалить улей Key из реестра.
function ValueExists(const Name: string): Boolean;
Проверить, существует ли в текущем ключе
параметр с именем Name. Весьма полезная функция,
т.к. чтение несуществующего параметра приводит к
исключительной ситуации
procedure WriteBinaryData(const Name: String; var Buffer; BufSize: Integer);
Записать в параметр с именем Name данные из буфера
Buffer размером BufSize. Если параметр существовал, то
он будет перезаписан. Если параметр не
существовал, то он будет создан. Это справедливо
и для всех последующих процедур записи
параметров
Остальные процедуры записи - WriteBool, WriteCurrency,WriteDate,WriteDateTime, WriteExpandString, WriteFloat, WriteInteger, WriteString, WriteTime имеют по два параметра - (имя ключа, значение ключа).
Ну вот, класс описали, теперь приведем парочку примеров.
Пример 1 - запись. var REG : TRegistry; begin REG := TRegistry.Create; REG.RootKey:=HKEY_LOCAL_MACHINE; REG.OpenKey('Software\Test',true); REG.WriteBool('Test1',true); REG.WriteInteger('Test2',12); REG.CloseKey; REG.Destroy; end;
Данный пример создает (если его не было) или открывает ключ реестра HKEY_LOCAL_MACHINE\Software\Test и записывает в него два параметра типа Boolean и Integer.
Пример 2 - чтение. var REG : TRegistry; B : Boolean; I : Integer; begin REG := TRegistry.Create; REG.RootKey:=HKEY_LOCAL_MACHINE; if REG.OpenKey('Software\Test',false) then begin if REG.ValueExists('Test1') then B:=REG.ReadBool('Test1') else ShowMessage('Параметр Test1 не найден'); if REG.ValueExists('Test2') then I:=REG.ReadInteger('Test2') else ShowMessage('Параметр Test2 не найден'); end else ShowMessage('Ключ HKEY_LOCAL_MACHINE\Software\Test не найден'); REG.CloseKey; REG.Destroy; end;
Данный пример открывает ключ (контролируя, есть ли он) и пытается читать параметры с проверкой, существуют ли они.
Задать вопрос | Наверх |
Класс INIFILES - работа с INI файлами. | * | * |
Почему иногда лучше использовать INI-файлы, а не реестр?
1. INI-файлы можно просмотреть и отредактировать в обычном блокноте.
2. Если INI-файл хранить в папке с программой, то при переносе папки на другой
компьютер настройки сохраняются.
3. Новичку в реестре можно запросто запутаться или (Боже упаси), чего-нибудь не
то изменить.
Поэтому для хранения параметров настройки программы удобно использовать стандартные INI
файлы Windows. Работа с INI файлами ведется при помощи
объекта TIniFiles модуля IniFiles. Краткое описание
методов объекта TIniFiles дано ниже.
Constructor Create('d:\test.INI');
Создать экземпляр объекта и связать его с
файлом. Если такого файла нет, то он создается, но
только тогда, когда произведете в него запись
информации.
WriteBool(const Section, Ident: string; Value: Boolean);
Присвоить элементу с именем Ident раздела Section
значение типа boolean
WriteInteger(const Section, Ident: string; Value: Longint);
Присвоить элементу с именем Ident раздела Section
значение типа Longint
WriteString(const Section, Ident, Value: string);
Присвоить элементу с именем Ident раздела Section
значение типа String
ReadSection (const Section: string; Strings: TStrings);
Прочитать имена всех корректно описанных
переменных раздела Section (некорректно описанные
опускаются)
ReadSectionValues(const Section: string; Strings: TStrings);
Прочитать имена и значения всех корректно
описанных переменных раздела Section. Формат :
имя_переменной = значение
EraseSection(const Section: string);
Удалить раздел Section со всем содержимым
ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
Прочитать значение переменной типа Boolean
раздела Section с именем Ident, и если его нет, то вместо
него подставить значение Default.
ReadInteger(const Section, Ident: string; Default: Longint): Longint;
Прочитать значение переменной типа Longint
раздела Section с именем Ident, и если его нет, то вместо
него подставить значение Default.
ReadString(const Section, Ident, Default: string): string;
Прочитать значение переменной типа String
раздела Section с именем Ident, и если его нет, то вместо
него подставить значение Default.
Free;
Закрыть и освободить ресурс. Необходимо
вызвать при завершении работы с INI файлом
Property Values[const Name: string]: string;
Доступ к существующему параметру по имени Name
Пример :
Procedure TForm1.FormClose(Sender: TObject); var IniFile:TIniFile; begin IniFile := TIniFile.Create('d:\test.INI'); { Создали экземпляр объекта } IniFile.WriteBool('Options', 'Sound', True); { Секция Options: Sound:=true } IniFile.WriteInteger('Options', 'Level', 3); { Секция Options: Level:=3 } IniFile.WriteString('Options' , 'Secret password', Pass); { Секция Options: в Secret password записать значение переменной Pass } IniFile.ReadSection('Options ', memo1.lines); { Читаем имена переменных} IniFile.ReadSectionValues('Options ', memo2.lines); { Читаем имена и значения } IniFile.Free; { Закрыли файл, уничтожили объект и освободили память } end;
Задать вопрос | Наверх |
Добавление элементов в контекстное меню "Создать" | * | * |
Задать вопрос | Наверх |
Настройка программы, которая открывает не зарегистрированные файлы | * | * |
Задать вопрос | Наверх |
Регистрация деинсталлятора для своей программы | * | * |
Задать вопрос | Наверх |
Автоматический запуск программы через реестр | * | * |
Задать вопрос | Наверх |
Я советую посетить и другие сайты, посвященные программированию. Это легко сделать по кольцу:
Algorithm project
: Кольцо сайтов, посвященных программированию (подробнее о проекте WebRing...) [ Предыдущие 5 сайтов | Предыдуший | Следующий | Следующие 5 сайтов | Выбрать сайт случайным образом | Список всех сайтов ]