Another way to more effectively use the registry is to take advantage of registry change notifications. An application can be efficiently notified of changes made within a registry key by using the RegNotifyChangeKeyValue function. This function allows you to tell the system what type of changes you want to be notified of and whether or not you wish to be notified of changes made within subkeys. Here is the function prototype:
LONG RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL fAsynchronous); |
The hkey parameter identifies the key for which you want to receive change notifications. The fWatchSubtree parameter indicates whether you want to be notified of changes within the entire tree below the specified key. The dwNotifyFilter parameter indicates which changes you want to be notified of. The dwNotifyFilter parameter can take any combination of the flags listed in Table 5-5.
Table 5-5. Flags that can be passed for RegNotifyChangeKeyValue's dwNotifyFilter parameter
Notification Flags | Description |
---|---|
REG_NOTIFY_CHANGE_NAME | Notification occurs when a subkey is added or deleted. |
REG_NOTIFY_CHANGE_ATTRIBUTES | Notification occurs when the attributes of the key, including the security descriptor information, changes. |
REG_NOTIFY_CHANGE_LAST_SET | Notification occurs when the value of the key, including the addition or deletion of values, changes. |
REG_NOTIFY_CHANGE_SECURITY | Notification occurs when the security descriptor of the key changes. |
The RegNotifyChangeKeyValue function can be used in one of two ways: synchronously or asynchronously. To use the function synchronously, pass FALSE as the value of fAsynchronous. In a synchronous call to RegNotifyChangeKeyValue, the calling thread is suspended until a registry notification occurs. If you want to use the function asynchronously, you must pass a valid event handle in the hEvent parameter and TRUE for the fAsynchronous parameter. Calling the function asynchronously causes the function to return immediately. The system will automatically signal the event kernel object when the next registry change (matching the specified filter) occurs.
I prefer the asynchronous feature of RegNotifyChangeKeyValue because it does not waste threads in your process. Remember that whether you are using the function asynchronously or not, each call to RegNotifyChangeKeyValue is good for only a single notification. The function must be called repeatedly for you to receive future notifications.
NOTE
If the thread that called RegNotifyChangeKeyValue terminates, the system cancels the request for notification. This is typically not a problem, because commonly the thread waiting on the event is the same thread that called RegNotifyChangeKeyValue.If the thread that called RegNotifyChangeKeyValue does terminate before a change notification occurs, the system signals the event, releasing any threads waiting on that event.
NOTE
To cause a thread to return from a synchronous call to RegNotifyChangeKeyValue without making a change to the key, your application must close the handle to the registry key.
The RegNotify sample application ("05 RegNotify.exe"), shown in Listing 52, demonstrates the asynchronous use of the RegNotifyChangeKeyValue function. The source code and resource files for the application are in the 05-RegNotify directory on the companion CD. The program simply monitors notifications for a registry key specified by the user.
When RegNotify is executed, the user enters a registry key for which he wants to receive automatic change notifications. The user then clicks the Watch button to begin the notification process for the specified registry key. Figure 5-4 shows the RegNotify sample application after new values have been added to the key being watched.
Figure 5-4. The dialog box for the RegNotify sample application after three new values have been added to HKLM\SOFTWARE\RegNotify
The notification process works like this: The RegNotify application creates a second thread, which enters into a loop that calls RegNotifyChangeKeyValue repeatedly for the selected key, enabling display of the value information in the read-only edit control. Each time a notification occurs, the event is signaled, causing WaitForSingleObjectEx to return WAIT_OBJECT_0. A return value of WAIT_OBJECT_0 causes the function to loop again for another notification.
When the user closes the application, the primary thread posts a user-mode asynchronous procedure call (APC) to the notification thread, which causes WaitForSingleObjectEx to exit with the value WAIT_IO_COMPLETION. The loop exits, causing the notification thread to exit.
NOTE
Using an APC as a form of interthread communication is sometimes desirable because it can be more efficient. It does not require the creation of a kernel object such as a semaphore or an event. When you use an APC for interthread communication, you frequently must create an APC callback function that is used as nothing other than a placeholder function for an APC.If you have not seen this technique in the past, the empty placeholder function can be initially confusing. For more information on this technique and other interthread communication mechanisms, see Chapter 2.
Listing 5-2. The RegNotify sample application
|