1. Computing
Monitoring Registry Changes
Page 2: Creating the Thread class for Registry monitoring
 More of this Feature
• Page 1: RegNotifyChange...
• Page 3: Sample project
• Page 4: Source CODE

Printer friendly versionPrinter friendly version
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Working with the Registry
• Threading in Delphi
• Message handling
• Writing components

• "Big Brother" - Part 1
• "Big Brother" - Part 2
• "Big Brother" - Part 3

Before we start adding code to a sample Delphi project capable of monitoring Registry changes we have to create a new thread object - the one that, in a loop, waits for a change to happen.

For the sake of simplicity we'll add this thread class in an existing project. First, start Delphi. By default a new project with one form is created. Second, add a TMemo component to that form. This is all we need, any change to the Registry will be added to the Memo. Now, we move onto creating that thread...

The TRegMonitorThread Class
New Delphi Thread Object To create a new Thread object, you simply point to (main Delphi menu) File | New | Other and select "Thread Object", a "New Thread Object" dialog box will ask you to specify the name for your class.
Name it 'TRegMonitorThread', click OK. This will add a new unit to your project, with a skeleton code (and an empty Execute function) that defines the TRegMonitorThread class as a class derived from TThread.

Note: if you have never worked with threads in Delphi - why not start now! Either way, "Threading in Delphi" has all the information about creating multithread applications with Delphi that you can think of.

Now, I'll show you some code snippets from the TRegMonitorThread class. Later, you'll have the option to download all the code from the article.

Let's see. The main code goes in the Execute procedure of the thread object. As explained in the beginning of the article, the code in the Execute procedure is in fact one big loop - executes until you terminate the monitoring process. In the loop, the code calls the WaitForSingleObject API that enters a wait state and uses almost no CPU cycles until a condition is met. The condition we are waiting for, is the event called by the RegNotifyChangeKeyValue function.

This is how the above looks when talking Delphi language:

procedure TRegMonitorThread.InitThread;
begin
  FReg.RootKey := RootKey;
  if not FReg.OpenKeyReadOnly(Key) then
  begin
    raise Exception.Create('Unable to open registry key ' + Key);
  end;
  FEvent := CreateEvent(nil, True, False, 'RegMonitorChange');
  RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
end;

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;

Note: The Execute function first calls the InitThread procedure that uses the values of the properties of the class to create the event and to make the first call to RegNotifyChangeKeyValue function. The properties of the TRegMonitorThread class provide a simpler way for a developer to supply values to the RegNotifyChangeKeyValue function and other structures defined inside the thread class.

Now, what happens when the wait loop traps a Registry change?
The fChangeData is a record type variable (exposed as a read-only property) in which we save the current value of the Key where the change has occurred. The code upon notification sends a user defined message to the window (Wnd parameter) that called the monitoring thread. And finally, we call the RegNotifyChangeKeyValue again.

This is, more or less, everything you need to enable Registry monitoring using Delphi. But, and there is always a "but", due to some situations when monitoring sub-keys is not working you'll need to redeclare the RegNotifyChangeKeyValue function by changing some parameters from Boolean to Integer, like this:

function RegNotifyChangeKeyValue(
  hKey: HKEY; bWatchSubtree: DWORD; 
  dwNotifyFilter: DWORD; 
  hEvent: THandle; 
  fAsynchronus: DWORD): Longint; stdcall;
external 'advapi32.dll' name 'RegNotifyChangeKeyValue';

Next, you are ready to add the code in the main project to call the TRegMonitorThread.

Next page > Sample project > Page 1, 2, 3

~ Zarko Gajic

©2014 About.com. All rights reserved.