Statement: Any group or individual other than CSDN who reprints this article must indicate the source and author.
The TRegistry class that comes with Delphi can only implement the basic operations of the registry. If we want to monitor changes in the registry in real time or scan all subkeys under a specific key in the registry, the TRegistry class is powerless. I gnawed at the SDK for a long time, and finally realized Delphi's monitoring and scanning of the registry. I didn't dare to keep it to myself, so I dedicated it to the majority of Delphi enthusiasts.
Monitoring changes in registry-related items requires an API: RegNotifyChangeKeyValue.
LONG RegNotifyChangeKeyValue(
HKEY hKey, // handle to an item to monitor
BOOL bWatchSubtree, // Whether to monitor the subkeys of this item
DWord dwNotifyFilter, // What changes to monitor
HANDLE hEvent, // Event object handle that accepts registry change events
BOOL fAsynchronous // Report before registry changes or after registry changes
);
Note that the hEvent above is the event object handle that accepts registry change events. We need to use API: CreateEvent to create a system event object.
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES structure
BOOL bManualReset, // Whether to automatically reset
BOOL bInitialState, // Whether to set the initial state
LPCTSTR lpName //The name of the event object
);
Create a new project and add a ListBox and two Buttons.
//First write an example of monitoring the registry
//Monitor all subkeys under the HKEY_CURRENT_USER/Software item
PRocedure TForm1.Button1Click(Sender: TObject);
var
hNotify: THandle;
hKeyx:HKEY;
dwRes: DWORD;
begin
hNotify := CreateEvent( nil, //Do not use SECURITY_ATTRIBUTES structure
FALSE, //Do not automatically reset
TRUE, //Set initial state
'RegistryNotify' //The name of the event object
);
if hNotify = 0 then
begin
Showmessage('CreateEvent failed.');
exit;
end;
if RegOpenKeyEx(HKEY_CURRENT_USER, //Follow the key
'Software', //Subkey
0, //reserved
KEY_NOTIFY, //for monitoring
hKeyx //Save handle
) <> ERROR_SUCCESS then
begin
CloseHandle( hNotify );
Showmessage('RegOpenKeyEx failed.');
exit;
end;
if RegNotifyChangeKeyValue( hKeyx, //Monitor subkey handle
TRUE, //Monitor the subkeys of this item
REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_LAST_SET,
hNotify, //Event object handle that accepts registry change events
TRUE //Report before registry changes
) <> ERROR_SUCCESS then
begin
CloseHandle( hNotify );
RegCloseKey( hKeyx );
Showmessage('RegNotifyChangeKeyValue failed');
exit;
end;
dwRes := WaitForSingleObject( hNotify, 60 * 1000 ); //Monitor for one minute
if dwRes = 0 then
Showmessage( 'Registry will be changed.' );
CloseHandle( hNotify );
RegCloseKey( hKeyx );
end;
It should be noted that API: WaitForSingleObject will not return until the registry change event occurs or times out. During this period, our program will lose response. The solution is to create a new thread and monitor the registry in the new thread.
Two other APIs are used to scan the registry: RegEnumKey and RegEnumValue.
LONG RegEnumKey(
HKEY hKey, // handle of the registry item to be scanned
DWORD dwIndex,//subkey serial number to be scanned
LPTSTR lpName,//The subkey name to be scanned
LPDWORD lpcbName, // The subkey name to be scanned occupies space
);
The method of using this function is: first assign 0 to dwIndex, call RegEnumKey; then Inc(dwIndex), and then call RegEnumKey until the return value is ERROR_NO_MORE_ITEMS, indicating that there are no more sub-items.
//Example of scanning the registry
//Only demonstrates how to enumerate one level of sub-items under HKEY_CURRENT_USER/Software
procedure TForm1.Button2Click(Sender: TObject);
var
buf : array [0..255] of char;
iRes : integer;
hKeyx:HKEY;
dwIndex, dwSize: DWORD;
begin
if RegOpenKeyEx( HKEY_CURRENT_USER, 'Software', 0, KEY_READ or
KEY_ENUMERATE_SUB_KEYS, hKeyx ) <> ERROR_SUCCESS then
begin
Showmessage('RegOpenKeyEx failed.');
exit;
end;
dwIndex := 0;
repeat
dwSize := 255;
iRes := RegEnumKey( hKeyx, dwIndex, buf, dwSize );
if iRes = ERROR_NO_MORE_ITEMS then
break
else if iRes = ERROR_SUCCESS then
begin
Listbox1.Items.Add(buf);
Inc(dwIndex);
end;
until iRes <> ERROR_SUCCESS;
RegCloseKey( hKeyx );
end;