Заявление: Любая группа или частное лицо, кроме CSDN, которое перепечатывает эту статью, должно указать источник и автора.
Класс TRegistry, поставляемый с Delphi, может выполнять только основные операции с реестром. Если мы хотим отслеживать изменения в реестре в реальном времени или сканировать все подразделы под определенным ключом реестра, класс TRegistry бессилен. Я долго грыз SDK и наконец понял, что Delphi контролирует и сканирует реестр. Я не осмелился оставить это себе, поэтому посвятил его большинству энтузиастов Delphi.
Для мониторинга изменений в элементах, связанных с реестром, требуется API: RegNotifyChangeKeyValue.
LONG RegNotifyChangeKeyValue(
HKEY hKey, // дескриптор элемента для мониторинга
BOOL bWatchSubtree, // Следует ли отслеживать подразделы этого элемента
DWord dwNotifyFilter, // Какие изменения отслеживать
HANDLE hEvent, // Дескриптор объекта события, который принимает события изменения реестра
BOOL fAsynchronous // Отчет до изменений реестра или после изменений реестра
);
Обратите внимание, что приведенный выше hEvent — это дескриптор объекта события, который принимает события изменения реестра. Нам нужно использовать API: CreateEvent для создания объекта системного события.
РУЧКА CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // структура SECURITY_ATTRIBUTES
BOOL bManualReset, // Автоматический ли сброс
BOOL bInitialState, // Устанавливать ли начальное состояние
LPCTSTR lpName //Имя объекта события
);
Создайте новый проект и добавьте ListBox и две кнопки.
//Сначала пишем пример мониторинга реестра
//Отслеживание всех подразделов в элементе HKEY_CURRENT_USER/Software
PROcedure TForm1.Button1Click(Отправитель: TObject);
вар
hУведомить: THandle;
hKeyx: HKEY;
dwRes: ДВОРД;
начинать
hNotify := CreateEvent( nil, //Не использовать структуру SECURITY_ATTRIBUTES
ЛОЖЬ, // Не выполнять автоматический сброс
TRUE, //Устанавливаем начальное состояние
'RegistryNotify' //Имя объекта события
);
если hNotify = 0, то
начинать
Showmessage('Создать событие не удалось.');
Выход;
конец;
if RegOpenKeyEx(HKEY_CURRENT_USER, //Следуем ключу
«Программное обеспечение», //Подключ
0, // зарезервировано
KEY_NOTIFY, //для мониторинга
hKeyx //Сохранить дескриптор
) <> ERROR_SUCCESS, тогда
начинать
CloseHandle(hNotify);
Showmessage('Ошибка RegOpenKeyEx.');
Выход;
конец;
if RegNotifyChangeKeyValue( hKeyx, //дескриптор подраздела монитора
TRUE, //отслеживаем подразделы этого элемента
REG_NOTIFY_CHANGE_NAME или REG_NOTIFY_CHANGE_LAST_SET,
hNotify, //Дескриптор объекта события, который принимает события изменения реестра
TRUE //Отчет до внесения изменений в реестр
) <> ERROR_SUCCESS, тогда
начинать
CloseHandle(hNotify);
RegCloseKey(hKeyx);
Showmessage('RegNotifyChangeKeyValue не удалось');
Выход;
конец;
dwRes := WaitForSingleObject( hNotify, 60 * 1000 // Мониторинг в течение одной минуты);
если dwRes = 0, то
Showmessage('Реестр будет изменен.');
CloseHandle(hNotify);
RegCloseKey(hKeyx);
конец;
Следует отметить, что API: WaitForSingleObject не вернется до тех пор, пока не произойдет событие изменения реестра или не истечет время ожидания. В течение этого периода наша программа потеряет ответ. Решение состоит в том, чтобы создать новый поток и отслеживать реестр в новом потоке.
Для сканирования реестра используются два других API: RegEnumKey и RegEnumValue.
ДЛИННЫЙ RegEnumKey(
HKEY hKey, // дескриптор сканируемого элемента реестра
DWORD dwIndex,//серийный номер подраздела для сканирования
LPTSTR lpName,//Имя подраздела для сканирования
LPDWORD lpcbName, // Имя сканируемого подраздела занимает пространство
);
Метод использования этой функции следующий: сначала присвойте 0 dwIndex, вызовите RegEnumKey, затем Inc(dwIndex), а затем вызовите RegEnumKey до тех пор, пока возвращаемое значение не станет ERROR_NO_MORE_ITEMS, указывая, что подэлементов больше нет.
//Пример сканирования реестра
//Показывает только, как перечислить один уровень подэлементов в HKEY_CURRENT_USER/Software
процедура TForm1.Button2Click(Отправитель: TObject);
вар
buf: массив [0..255] символов;
iRes: целое число;
hKeyx: HKEY;
dwIndex, dwSize: DWORD;
начинать
если RegOpenKeyEx( HKEY_CURRENT_USER, «Программное обеспечение», 0, KEY_READ или
KEY_ENUMERATE_SUB_KEYS, hKeyx) <> ERROR_SUCCESS, затем
начинать
Showmessage('Ошибка RegOpenKeyEx.');
Выход;
конец;
двиндекс: = 0;
повторить
dwSize: = 255;
iRes := RegEnumKey(hKeyx, dwIndex, buf, dwSize);
если iRes = ERROR_NO_MORE_ITEMS, то
перерыв
иначе, если iRes = ERROR_SUCCESS, тогда
начинать
Listbox1.Items.Add(buf);
Inc(dwИндекс);
конец;
пока iRes <> ERROR_SUCCESS;
RegCloseKey(hKeyx);
конец;