Реестр и средства работы с реестром. Лабораторная работа №7.


Цель работы:  освоение методики и функций Win32 для работы с реестром. Знакомство с компонентом Registry, его свойствами и методами.

Структура реестра

Реестр — это база данных, которая является частью операционной системы Windows 9x или NT.

Реестр хранит информацию, используемую  для инициализации и конфигурирования приложений и управляет доступом к ней. Все технологии на платформе Windows  интенсивно используют реестр.

Реестр Windows 9x состоит из файлов user.dat и system.dat, представляющих собой скрытые файлы, находящиеся в каталоге \Windows. ПЕРЕД началом работы с реестром необходимо сохранить копию этих файлов.     

Реестр имеет иерархическую структуру и состоит из разделов и пар параметр-значение.  Структура реестра напоминает иерархическую структуру каталогов Windows — разделы можно представлять себе в виде папок, а пары параметр-значение — в виде файлов. Редактор реестра RegEdit — основной инструмент пользователя для манипуляции с реестром, предоставляемый Microsoft.

Разделы

Раздел — это узел структуры реестра. Он состоит из подразделов и пар параметр-значение. Имя подраздела должно быть уникальным внутри его родительского раздела. Для отделения имен родительских разделов от дочерних используется символ \

HKEYs

Разделы HKEYs — это средство доступа к разделам реестра самого верхнего уровня. Они определяются в  API реестра и являются точкой входа в дерево реестра. В реестре есть ДВА основных раздела —  HKEY_LOCAL_MACHINE и HKEY_USERS (которые хранятся соответствен-но в файлах system.dat и  user.dat) и четыре дополнительных раздела.

Пары параметр-значение

Пара параметр-значение — компонент реестра, который непосредственно хранит данные. Используя путь к разделу и имя параметра, можно считать значение из пары параметр-значение.

Значение, находящееся в паре, может иметь один из нескольких типов. Три основных типа данных- двойное слово (DWORD), строка (String) и двоичное значение (Binary).

                                                                          Редактор реестра

Для запуска редактора реестра используется меню Пуск-> Выполнить. В окне имени файла необходимо ввести regedit и нажать ОК. Редактор реестра дает возможность просматривать содержимое реестра, создавать и удалять подразделы и пары параметр-значение, выполнять экспорт-импорт всего реестра или его части.

НИКОГДА НЕ УДАЛЯЙТЕ ПОДРАЗДЕЛЫ и ПАРЫ ПАРАМЕТР_ЗНАЧЕНИЕ, которые ВЫ не создавали!

Редактор реестра поддерживает  только три типа данных (перечисленные выше) из 9. Для выполнения операций с данными других типов необходимо использовать функции Win32 API.

Функции Win32 для работы с реестром

  1. Открытие и закрытие родительского раздела.

Перед началом выполнения любых операций с разделом его необходимо открыть ( как и при работе с любой базой данных). Для открытия раздела используется функция

RegOpenKeyEx

( HKEY_LOCAL_MACHINE,  // имя корневого раздела

‘SOFTWARE\Borland’,            // имя открываемого подраздела

0,                                              // зарезервированное значение

KEY_ALL_ACCESS,             //  вид доступа к разделу    — полный доступ

hkkey   )                                  //  возвращаемое значение — Handle раздела — типа HKEY.

При успешном открытии возвращается ERROR_SUCCESS, т.е. 0. Если подраздел не существует, возвращается 2.

После окончания работы с подразделом его необходимо закрыть, используя функцию

RegCloseKey (hkkey);

  1. Создание подразделов.

Для создания подраздела в существующем разделе используется функция RegCreateKeyEx, с помощью которой можно  открыть существующий раздел, или создать новый подраздел. Пример вызова функции

RegCreateKeyEx

( HKEY_LOCAL_MACHINE,  // имя корневого раздела

‘SOFTWARE\myrazd’,         // имя создаваемого подраздела

0,                                        //  резерв, всегда 0

»,         // имя класса или типа объекта раздела — пустая строка

REG_OPTION_NON_VOLATILE,   //  постоянный раздел

KEY_ALL_ACCESS,         //  вид доступа к разделу

nil,                                       //  атрибут безопасности

hkkey,                                 //  описатель раздела, тип HKEY

@result ) : integer  — код ошибки   //   Result — типа DWORD.

Параметр result типа DWORD принимает значения REG_CREATED_NEW_KEY или

REG_OPENED_EXISTING_KEY.

  1. Установка значения параметра.

Функция RegSetValueEx создает в открытом или созданном разделе пару параметр-значение. Пример вызова функции

RegSetValueEx

( описатель созданного или открытого раздела,

имя пары параметр-значение,

0,                            // резерв — всегда 0

REG_SZ,               //  тип значения — строка с 0 в конце

Strd,                       // переменная типа  Pchar, которой присвоено необходимое значение

Length (strd)          //  длина значения

) ;

  1. Получение значения параметра

Для чтения значения параметра используется функция RegQueryValueEx.

Необходимо описать переменные:

dwType : DWORD  — тип возвращаемого значения

buf :  Array [1..n] of char -массив для получения значения строкового параметра

len  : DWORD — длина буфера

и присвоить переменным значения  dwType := REG_SZ;

len:= N;

Вызов функции для чтения значения параметра

Error := RegQueryValueEx (

hkkey,                 //  handle  открытого раздела

имя параметра,  // имя должно быть записано в апострофах

nil,                      // зарезервированное значение

@dwType,         // адрес типа возвращаемого значения

@buf,                //  адрес буфера

@len );

if  Error = ERROR_SUCCESS then  //  если нет ошибки — получить значение параметра

for k:=1 to len-1 do  str := str + buf [ k ];

  1. Удаление раздела и его значений — функция RegDeleteKey.
  2. Получение информации из открытого раздела — RegQueryInfoKey (). Функция возвращает:
  • количество подразделов;
  • длину самого длинного имени подраздела;
  • количество пар;
  • длину самого длинного имени параметра;
  • длину самого длинного значения;
  1. Просмотр пар параметр- значение — функция RegEnumValue (). Среди прочего, возвращает информацию о типе значения данной пары.
  2. Уведомление приложения об изменениях в разделе — RegNotifyChangeKeyValue. Она может сгенерировать событие при изменении имен раздела или создании и удалении раздела (для раздела или подраздела). Пример использования данной функции приведен ниже

procedure TForm1.Button1Click(Sender: TObject);

var

ev : Thandle;      err : dword;

hkkey : hkey;    result : DWORD;

begin

ev:=CreateEvent(nil,true,false,’name’);

err:=  RegCreateKeyEx

( HKEY_LOCAL_MACHINE,  //

‘SOFTWARE’,         //

0,

»,

REG_OPTION_NON_VOLATILE,

KEY_ALL_ACCESS,

nil,

hkkey,

@result );

RegNotifyChangeKeyValue     (hkkey,True,

REG_NOTIFY_CHANGE_NAME,

ev,true);

waitforSingleObject( ev, infinite);

ShowMessage (‘ Реестр изменен ‘);

end;

Использование компонента Registry

 

Пример1. Приведенный фрагмент по введенному в окне редактирования пути (он может быть пустым) к разделу реестра (расположенного в HKEY_LOCAL_MACHINE\SOFTWARE) дает возможность получить список его подразделов, а для подраздела, имеющего список пар параметр-значение — список имен параметров. Не забудьте добавить registry  в  uses.

procedure TForm1.Button1Click(Sender: TObject);

var  reg : Tregistry;      res : boolean;    strs : TstringList;    i : integer;

begin

ListBox1.Clear;  ListBox2.Clear;

reg:=Tregistry.Create;   strs:=TstringList.Create;

reg.RootKey:=HKEY_LOCAL_MACHINE;

reg.OpenKey(‘SOFTWARE\’+Edit1.Text,False);

if res then label1.caption:=’ok’;

// получение списка имен ключей (подразделов) раздела, путь которого указан  строкой

// SOFTWARE\ и строкой, введенной в окне редактирования Edit1

reg.GetKeyNames(strs);

label2.Caption:=inttostr(strs.count);

for i:=1 to strs.count-1 do listbox1.Items.add(strs.strings[i]);

//  получить имена параметров данного раздела

reg.GetValueNames(strs);

label2.Caption:=inttostr(strs.count);

for i:=1 to strs.count do  listbox2.Items.add(strs.strings[i-1]);

reg.CloseKey;

end;

Пример 2. Поиск в разделе реестра заданного имени подраздела.

Const

RtK : array[1..6] of HKEY = (HKEY_CLASSES_ROOT,  HKEY_CURRENT_USER,

HKEY_LOCAL_MACHINE, HKEY_USERS,                         HKEY_CURRENT_CONFIG, HKEY_DYN_DATA);

RKS: array[1..6] of String = (‘HKEY_CLASSES_ROOT’, ‘HKEY_CURRENT_USER’,

‘HKEY_LOCAL_MACHINE’,   ‘HKEY_USERS’,        ‘HKEY_CURRENT_CONFIG’, ‘HKEY_DYN_DATA’);

function SearchKey(MainKey:word; // номер одного из 6 разделов реестра

SubKey:String;                                  // подраздел, с которого начинается поиск

KeyF:String                                     // имя подраздела, которое требуется найти

):string;

var I:dword;     value:TRegKeyInfo;    Strs:TStringList;     path : string;

begin

Strs:=TStringList.create;

reg.RootKey:= Rtk[MainKey] ;

// задаем подраздел, в котором необходимо искать

reg.OpenKey(SubKey,false);

if reg.GetKeyInfo(value) then

Begin     // при отсутствии подраздела – выход

if value.NumSubKeys=0 then exit;

reestr.GetKeyNames(Strs);

reestr.CloseKey;

For I := 1 to Value.NumSubKeys do

Begin        // получение пути к разделам

if subkey=’\’ then path:=’\’+Strs.Strings[i-1]  else path:=subkey+’\’+Strs.Strings[i-1];

if Strs.Strings[i-1]=KeyF  then Listbox1.Items.add(Rks[MainKey]+Path); // запись результата

// вызов  SearchKey (     ); — фактические параметры указать самостоятельно, исходя из логики  процедуры поиска

End;

reg.CloseKey;

end;

end;

ВЫПОЛНЕНИЕ РАБОТЫ

Список заданий

  1. Написать приложение для создания в разделе HKEY_LOCAL_MACHINE\SOFTWARE подраздела, имя которого задается путем ввода с клавиатуры и записи в созданный раздел пары параметр-значение. Имя параметра и значение должны вводиться с клавиатуры.
  2. Добавить возможность редактирования с помощью разработанного приложения значений пар параметр-значение_строкового типа и проверить правильность выполнения редактирования на созданной в п.1 паре.
  3. Вывести список имен подразделов раздела, имя которого задается вводом с клавиатуры.
  4. Вывести список имен параметров пар заданного раздела.
  5. Вывести список типов значений параметров пар заданного раздела.

Примечание. п.1-п.5 выполнить с использованием функций Win32 API.

  1. Проверить работу фрагментов программ, приведенных в примерах 1 и 2.

Список индивидуальных заданий

  1. Разработать приложение для нахождения количества подразделов в каждом из 6 основных разделов реестра и самого длинного пути к подразделу. Данное приложение должно запускаться на данном ПК не более 5 раз (информацию о количестве запусков хранить в реестре).
  2. Разработать приложение для поиска в заданном разделе реестра параметра по его имени. Результат поиска – список путей к подразделам реестра, в которых хранится параметр с заданным именем. Дать предложения по повышению скорости работы приложения за счет использования дихотомического поиска.
  3. Разработать приложение для поиска в заданном разделе реестра всех параметров строкового типа, длина значений которых не превышает K (значения K и раздел реестра должны задаваться вводом с клавиатуры).

ОТЧЕТ О РАБОТЕ должен содержать:

1   Описание постановки задач, алгоритмов решения задач  и его программной реализации.

  1. Полученные результаты.

Литература

Чен В., Берри В. Реестр Windows Nt  для  профессионалов. — СПб: «Издательство Питер», 1999.