Discussion:
XP Registry monitoring - RegNotifyChangeKeyValue and CreateEvent.
(too old to reply)
R.Wieser
2011-01-10 13:15:39 UTC
Permalink
Hello all,

Just now I felt the need to write some code to monitor changes in the
registry.

It led me to the RegNotifyChangeKeyValue function on the MS site, which also
contained some example-code.

When I read it I got a bit put-off by the round-about way you seem to need
to use it: You either use it in a "don't return before you have something"
mode (freezing your program/thread with no described way to un-freeze it !)
or by using an event-object which you than effectivily *poll* using a
"WaitFor ....Object..." function.

So, you either freeze the program/thread completely, or freeze it for short
whiles. :-(

Isn't there *any* way to just create something which will message me about
changes (maybe using a WM_... message or a callback), but will also allow
itself to be ended/terminated without my (main) program having to wait until
the next time it wakes up ?

Regards,
Rudy Wieser

P.s.
Before someone thinks of using StartTrace, I've tried it. Although the
command claims everything went O.K. (return-value == 0) the returned
session-handle is not even accepted by a, for testing-purposes,
directly-following CloseTrace command (return-value == 6 : invalid entry).
A second time using StartTrace fails because some file(?) is already open
...
Gunnar
2011-01-10 13:44:49 UTC
Permalink
Hi Rudy,
Post by R.Wieser
You either use it in a "don't return before you have something"
mode (freezing your program/thread with no described way to un-freeze it !)
the described way to un-freeze it is to close the registry handle you are
monitoring.
Post by R.Wieser
Isn't there *any* way to just create something which will message me about
changes
Just call PostMessage from the thread that monitors the registry ...

-Gunnar
R.Wieser
2011-01-11 18:00:12 UTC
Permalink
Hello Gunnar,
Post by Gunnar
the described way to un-freeze it is to close the registry
handle you are monitoring.
That does work under XP, but not under W98se. The former shows the thread
being closed when the monitored key is closed, the latter just continues
monitoring.

W98se does not seem to have any problem with closing the thread the command
is in when the main thread is closed though. Phew.

Seems I did remember that "no way to unfreeze" right after all. :-)

Regards,
Rudy Wieser
Post by Gunnar
Hi Rudy,
Post by R.Wieser
You either use it in a "don't return before you have something"
mode (freezing your program/thread with no described way to
un-freeze it !)
the described way to un-freeze it is to close the registry handle
you are monitoring.
Post by R.Wieser
Isn't there *any* way to just create something which will message
me about changes
Just call PostMessage from the thread that monitors the registry ...
-Gunnar
Leo Davidson
2011-01-10 16:00:37 UTC
Permalink
Post by R.Wieser
or by using an event-object which you than effectivily *poll* using a
"WaitFor ....Object..." function.
The whole point of events (and similar waitable HANDLE objects) and
the Wait* and MsgWait* functions is that you *don't* use polling.

(Unless you do something silly like call the Wait* functions in a loop
with zero timeout, but why would you do that?)

You collect all the handles and/or window messages your program is
interested in and then call an API which puts your program to sleep
until one of those handles is signalled, or one of the messages is
received.

Which API you use depends on what combination of things you are
waiting on. (If it's just one handle you can use WaitForSingleObject;
if it's several WaitForMultipleObjects; if there are also window
messages then MsgWaitForMultipleObjects; etc.)

One thing to keep in mind with RegNotifyChangeKeyValue is that you
should re-establish the wait handle *before* you process the change.
That way if the registry is changed again after or while you are
reading the values the handle will always be set again and you'll
process whatever happened correctly.
Gunnar
2011-01-10 16:29:27 UTC
Permalink
Post by Leo Davidson
One thing to keep in mind with RegNotifyChangeKeyValue is that you
should re-establish the wait handle *before* you process the change.
That way if the registry is changed again after or while you are
reading the values the handle will always be set again and you'll
process whatever happened correctly.
Article ID: 236570
On Microsoft Windows NT, Microsoft Windows 2000, and Microsoft Windows XP
(and Vista and W7) calling RegNotifyChangeKeyValue() for a particular key
handle causes change notifications to continue to occur for as long as the
key handle is valid. This causes a second call to RegNotifyChangeKeyValue()
to return immediately, if any changes have occurred in the interim period
between the first and second calls. If the API is being used asynchronously,
the passed event handle will be signaled immediately if any interim changes
have occurred.

Microsoft Windows 98 does not keep track of interim changes. Calling
RegNotifyChangeKeyValue only notifies you of changes occurring after the
call.
Leo Davidson
2011-01-11 06:29:33 UTC
Permalink
Post by Gunnar
Article ID: 236570
On Microsoft Windows NT, Microsoft Windows 2000, and Microsoft Windows XP
(and Vista and W7) calling RegNotifyChangeKeyValue() for a particular key
handle causes change notifications to continue to occur for as long as the
key handle is valid.
Thanks Gunnar, I didn't know about that. I haven't had reason to use
the API in a long time and I don't think that text was there
originally (or I had to support Win9x back then; not sure). Nice to
see the API is better than I thought!
R.Wieser
2011-01-11 16:30:12 UTC
Permalink
Post by Leo Davidson
The whole point of events (and similar waitable HANDLE objects)
and the Wait* and MsgWait* functions is that you *don't* use polling.
You will have to poll I'm afraid : Those Wait* commands will not return
unless something has happened, or they time-out.

Keeping them waiting forever would be silly, as the RegNotifyChangeKeyValue
can do that itself.

The way I saw it you needed to call such a Wait* command with a small
time-out to be able to check if the thread it was running in needed to
close.

Luckily Gunnar gave me a doh! moment when he mentioned that closing the
monitored key also causes the RegNotifyChangeKeyValue to return.

But if that is so what than are, in this case, that CreateEvent and Wait*
instructions good for ? <blink>

And yes, I mean that seriously.
Post by Leo Davidson
One thing to keep in mind with RegNotifyChangeKeyValue is that
you should re-establish the wait handle *before* you process the
change.
Thanks for that hint, will keep it in mind.

Regards,
Rudy Wieser


-- Origional message --
Post by Leo Davidson
or by using an event-object which you than effectivily *poll* using a
"WaitFor ....Object..." function.
The whole point of events (and similar waitable HANDLE objects) and
the Wait* and MsgWait* functions is that you *don't* use polling.

(Unless you do something silly like call the Wait* functions in a loop
with zero timeout, but why would you do that?)

You collect all the handles and/or window messages your program is
interested in and then call an API which puts your program to sleep
until one of those handles is signalled, or one of the messages is
received.

Which API you use depends on what combination of things you are
waiting on. (If it's just one handle you can use WaitForSingleObject;
if it's several WaitForMultipleObjects; if there are also window
messages then MsgWaitForMultipleObjects; etc.)

One thing to keep in mind with RegNotifyChangeKeyValue is that you
should re-establish the wait handle *before* you process the change.
That way if the registry is changed again after or while you are
reading the values the handle will always be set again and you'll
process whatever happened correctly.
Leo Davidson
2011-01-11 19:32:29 UTC
Permalink
Post by R.Wieser
You will have to poll I'm afraid : Those Wait* commands will not return
unless something has happened, or they time-out.
If they don't return until something happens, that isn't polling;
that's waiting. Waiting is good. If your program has nothing to do it
can go to sleep and consume zero resources. When something happens
that it is waiting for then OS will wake it up. That's (usually) the
ideal way to write apps.

This assumes that you are in control of your app's message loop and
can replace the GetMessage with a MsgWaitForMultipleObjects (followed
by PeekMessage with PM_REMOVE). If you can do that then your program
can respond to the registry change without blocking its other
activities, without polling and without creating an extra thread.

If you are not in control of your app's message loop (e.g. because
you're using a framework like MFC which hides it from you) then you
may not have a good place to put a MsgWaitForMultipleObjects call. You
would probably need to spawn your own thread to do the waiting,
regardless of which style of RegNotifyChangeKeyValue you choose to
use. If this single registry key is definitely going to be the only
thing your program will ever need to respond to then I guess it
doesn't really matter which style of RegNotifyChangeKeyValue you use.
But it's a good idea to use the wait-handle style: If your program one
day needs to wait on another handle (e.g. a second registry key, or a
file changing, a process exiting, etc. etc.) then it will be able to
do so using the same thread at zero extra cost (and again without ever
polling).
Post by R.Wieser
The way I saw it you needed to call such a Wait* command with a small
time-out to be able to check if the thread it was running in needed to
close.
The timeout is up to you and can be infinite. If you want to be able
to signal to the thread to close the usual way is to create another
event which the thread also waits on. When you want the thread to
exit, signal the event to wake the thread. When the thread wakes from
its waiting state it should check which event(s) woke it and respond
appropriately.
R.Wieser
2011-01-11 21:26:53 UTC
Permalink
Hello Leo,
Post by Leo Davidson
If they don't return until something happens, that isn't polling;
I agree, I call that Freezing. :-)
Post by Leo Davidson
This assumes that you are in control of your app's message
loop and can replace the GetMessage with a
MsgWaitForMultipleObjects (followed by PeekMessage
with PM_REMOVE).
I'm in full control of it (I'm one of the few guys still programming in
Assembly, but have not had any formal education in it). I will need to look
that method up and see if I can get it to work.
Post by Leo Davidson
You would probably need to spawn your own thread
to do the waiting,
That is what I'm currently doing. The easy way out I guess.
Post by Leo Davidson
...
it will be able to do so using the same thread at zero
extra cost (and again without ever polling).
As far as I can tell that would be good for a static number of things to
monitor. My intention is, at this moment, to make it a bit more like a tool
for (temporarily) keeping tabs on one or more keys.
Post by Leo Davidson
If you want to be able to signal to the thread to close
the usual way is to create another event which the
thread also waits on.
Thanks for that, I did not even think of doing it that way.

Regards,
Rudy Wieser
Post by Leo Davidson
You will have to poll I'm afraid : Those Wait* commands will not return
unless something has happened, or they time-out.
If they don't return until something happens, that isn't polling;
that's waiting. Waiting is good. If your program has nothing to do it
can go to sleep and consume zero resources. When something happens
that it is waiting for then OS will wake it up. That's (usually) the
ideal way to write apps.

This assumes that you are in control of your app's message loop and
can replace the GetMessage with a MsgWaitForMultipleObjects (followed
by PeekMessage with PM_REMOVE). If you can do that then your program
can respond to the registry change without blocking its other
activities, without polling and without creating an extra thread.

If you are not in control of your app's message loop (e.g. because
you're using a framework like MFC which hides it from you) then you
may not have a good place to put a MsgWaitForMultipleObjects call. You
would probably need to spawn your own thread to do the waiting,
regardless of which style of RegNotifyChangeKeyValue you choose to
use. If this single registry key is definitely going to be the only
thing your program will ever need to respond to then I guess it
doesn't really matter which style of RegNotifyChangeKeyValue you use.
But it's a good idea to use the wait-handle style: If your program one
day needs to wait on another handle (e.g. a second registry key, or a
file changing, a process exiting, etc. etc.) then it will be able to
do so using the same thread at zero extra cost (and again without ever
polling).
Post by Leo Davidson
The way I saw it you needed to call such a Wait* command with a small
time-out to be able to check if the thread it was running in needed to
close.
The timeout is up to you and can be infinite. If you want to be able
to signal to the thread to close the usual way is to create another
event which the thread also waits on. When you want the thread to
exit, signal the event to wake the thread. When the thread wakes from
its waiting state it should check which event(s) woke it and respond
appropriately.

Loading...