A feladat megoldásához a RegNotifyChangeKeyValue Windows API függvényt fogjuk felhasználni, mely egy megadott Registry bejegyzést, valamint annak albejegyzéseit képes figyelni, és változás esetén üzenetet küldeni programunknak. Nézzük, hogyan is épül fel:

RegNotifyChangeKeyValue
LONG RegNotifyChangeKeyValue(
HKEY hKey,
BOOL bWatchSubtree,
DWORD dwNotifyFilter,
HANDLE hEvent,
BOOL fAsynchronous
);
Paraméterek
HKEY hKey
A megnyitandó Registry kulcs megnevezése.
BOOL bWatchSubtree
Ha ez a paraméter igaz értéket kap, akkor a hKey-ben megadott bejegyzés albejegyzéseinek a változásáról is értesítést kapunk.
DWORD dwNotifyFilter
A változás típusát állíthatjuk be a segítségével. A következő értékeket veheti fel:
| Érték |
Jelentés |
| REG_NOTIFY_CHANGE_NAME |
Egy kulcs hozzáadásáról vagy törléséről kapunk figyelmeztetést. |
| REG_NOTIFY_CHANGE_ATTRIBUTES |
Egy kulcs attribútumának megváltozását figyelhetjük vele. |
| REG_NOTIFY_CHANGE_LAST_SET |
Egy adott kulcs értékének megváltozásáról figyelmeztet. Ide tartozik a kulcs értékének hozzáadása, törlése, vagy megváltoztatása. |
| REG_NOTIFY_CHANGE_SECURITY |
A kulcs biztonsági leírásának (security descriptor) megváltozását figyelhetjük vele. |
HANDLE hEvent
Eseményleíró. Amennyiben az fAsynchronous paraméter igaz értéket kap, a Registry kulcs megváltozásáról azonnali figyelmeztetést kapunk. Amennyiben a paraméter hamis, a hEvent nem kerül felhasználásra.
BOOL fAsynchronous
Amennyiben ez a paraméter igaz, a függvény azonnal visszatérési értéket szolgáltat, melyben jelzi a Registry kulcs megváltozását.
Visszatérési érték
A függvény sikeres futása esetén a visszatérési érték ERROR_SUCCESS lesz. Ellenkező esetben egy hibakódot kapunk vissza.
Mivel a fent ismertetett függvény a meghívása után folyamatosan figyeli a Registry megadott kulcsát, azt célszerű egy külön szálon futtatni, így alkalmazásunk továbbra is teljes értékűen használható. Mindehhez a TThread osztályból származtatnunk kell egy új objektumot. A Delphi File menüjének New menüpontjában válasszuk a Thread Object elemet. Adjuk meg a létrehozandó objektum nevét. Esetünkben ez a TRegMonitorThread lesz. Azonnal létrejön egy Execute nevű eljárás, melyben az adott szál tényleges funkcióját kell megadnunk. Esetünkben itt hívjuk meg a RegNotifyChangeKeyValue függvényt.
procedure TRegMonitorThread.Execute;
begin
InitThread;
while not Terminated do
begin
if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
begin
fChangeData.RootKey := RootKey;
fChangeData.Key := Key;
SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
ResetEvent(FEvent);
RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
end;
end;
end;
Láthatjuk, hogy az Execute metódusban létrehoztunk egy ciklust, mely mindaddig fut, míg le nem zárjuk az alkalmazást. A ciklusmagban meghívjuk a WaitForSingleObject API függvényt, mely egy várakozó állapotot hoz létre mindaddig, míg az FEvent által meghatározott esemény végre nem hajtódik. Esetünkben ez a RegNotifyChangeKeyValue függvény sikeres futása lesz. Az fChangeData rekord típusú változóban tároljuk el annak a kulcsnak a nevét, melyben a változás bekövetkezett. A SendMessage függvény meghívásával pedig annak az alkalmazásnak küldünk visszajelzést a Registry megváltozásáról, amelyik meghívta a Thread-et. Esetünkben ez a saját programunk lesz. Nézzük, hogyan is tudjuk meghívni a fenti szálat.
procedure TForm1.MonitoringON;
begin
RegMonitorThread1 := TRegMonitorThread.Create;
Status:=True;
if ComboBox1.Text<>'' then
begin
with RegMonitorThread1 do
begin
FreeOnTerminate:=True;
Wnd := Form1.Handle;
Key := 'Software\'+ComboBox1.Text;
RootKey := HKEY_LOCAL_MACHINE;
WatchSub := True;
Resume;
end;
Label1.Caption:='Status: ON';
end;
end;
Láthatjuk, hogy átadjuk a RegMonitorThread1-nek a megfelelő paramétereket, így az alkalmazásunk ablakleíróját és a vizsgálandó Registry kulcs nevét, valamint a WatchSub igazra állításával jelezzük, hogy az albejegyzések változását is figyelni szeretnénk.
A mellékelt példaprogramban egy ComboBox-ba betöltjük a Registry HKEY_LOCAL_MACHINE/Software könyvtárában található összes szoftver nevét. Ezek közül ki kell választanunk azt, melyet figyelni szeretnénk. Ezután bármilyen változás következzék be ezen a bejegyzésen, vagy annak bármely albejegyzésén, arról figyelmeztetést kapunk, melyet egy Memo-ba íratunk ki. A példa használatának megkönnyítésére létrehoztunk két nyomógombot, melyek segítségével lehetőségünk van a kiválasztott helyre egy Teszt nevű kulcsot létrehozni, valamint kitörölni. Így nem kell a regisztrációs adatbázisunkban kutakodni. A Registry figyelését a Monitoring OFF nyomógombbal függeszthetjük fel. Mindehhez csak a programszálunk Suspend metódusát kell meghívni.
procedure TForm1.Button2Click(Sender: TObject);
begin
if Status then
begin
RegMonitorThread1.Suspend;
Label1.Caption:='Status: OFF';
end;
end;
Miután befejeztük az alkalmazás futtatását, a szálat is le kell bontanunk a Terminate metódus segítségével.
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Status then
RegMonitorThread1.Terminate;
end;
A példaprogramban a Form stílusát StayOnTop-ra állítottuk, így mindig figyelemmel kísérhetjük a Registry változásait. Nagyon jó szolgálatot tehet akkor a most bemutatásra került program, mikor szeretnénk figyelemmel kísérni, hogy egy adott alkalmazás mikor változtatja meg beállításait a regisztrációs adatbázisban.