癥狀RegNotifyChangeKeyValue() API 允許應用程式以接收事件通知的指定登錄機碼和其子項中更改。
在 MicrosoftWindowsNT、 Microsoft Windows 2000 和 MicrosoftWindowsXP 對特定關鍵柄調用 RegNotifyChangeKeyValue() 導致更改通知以繼續使用在發生只要密鑰柄是有效。 這將導致二調用 RegNotifyChangeKeyValue() 回到立即, 如果在第一和第二個調用之間過渡期有發生任何更改。 傳遞事件控制代碼如果正在使用非同步, API 將被通知立即如果發生了任何臨時更改。
Microsoft Windows 98 不不跟蹤的臨時更改。 調用 RegNotifyChangeKeyValue 僅通知您的調用後發生更改。
解決方案您可能不關心臨時更改。 相反, 要只接收通知對將來更改 RegNotifyChangeKeyValue() 調用後發生。
下列方法之一可用於確保不對臨時更改接收通知:
| • |
關閉並重新開啟項。 返回新鍵控點未註冊用於更改通知。 |
| • |
使用非同步 RegNotifyChangeKeyValue() 並等待使用 WaitForSingleObject() 零逾時事件上。 這將清除可能臨時通知。 如果發生任何更改, 沒有損害是完成, 像等待與 WAIT_TIMEOUT 立即返回。 然後立即再次調用 API 來捕捉將來更改。 多線程應用程式應使用第二種, 因為它避免了關閉註冊表柄出從下另一個線程可能正在使用它的可能性。 有關樣本實現此二方法, 請參閱本文末尾代碼。 |
狀態此行為是設計使然。
更多資訊有幾個要處理註冊表更改通知時牢記事項:
當與檔案更改通知 API, RegNotifyChangeKeyValue() 不返回任何指示以什麼在登錄機碼或其子項或值已更改。 以便它可以確定了哪些更改程式必須知道的項或值之前對通知, 狀態。
沒有更改與通知不一對一關聯性。 接收更改通知, 時有實際上可能已大量註冊表更改。
範例程式碼
那些使用者與檔案過更改通知, 知道 FindFirstChangeNotification() 可用於接收目錄中只對將來更改通知。 然後可以使用 FindNextChangeNotification() 接收更改臨時檔案。 確保, 是不丟失通知。 遺憾, 還有沒有內建類似函數的註冊表更改通知。 以下範例程式碼說明如何?這些函數使用二方法 " 解決辦法 " 部分中列出。 實現下列功能:
| • |
RegFindFirstChange() |
| • |
RegFindNextChange() |
| • |
RegFindCloseChange() |
//**********************************************************************// // This program demonstrates how to work with registry change// notifications. In particular, it shows how to either receive// or ignore interim registry changes (for example, those that occur in// the period between receiving a notification and the next call// to RegNotifyChangeKeyValue().// // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED// TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A// PARTICULAR PURPOSE.// // Copyright (C) 1999 Microsoft Corporation. All rights reserved.// //**********************************************************************#include <windows.h>#include <conio.h>#include <stdio.h>#include <tchar.h>// defined constants#define MONITOR_TOPKEY HKEY_LOCAL_MACHINE#define MONITOR_SUBKEY TEXT("Software//Temp")// structure used internally by RegFindFirst/NextChange()typedef struct _REG_CHANGE_DATA { HKEY hKey; BOOL bWatchSubtree; DWORD dwNotifyFilter;} REG_CHANGE_DATA, *LPREG_CHANGE_DATA;// function prototypesHANDLE RegFindFirstChange( HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, LPREG_CHANGE_DATA lprcd );BOOL RegFindNextChange( HANDLE hChange, LPREG_CHANGE_DATA lprcd );BOOL RegFindCloseChange( HANDLE hChange );void DisplayError( LPTSTR szAPI, DWORD dwError );//**********************************************************************// // _tmain() -- becomes main() for ANSI or wmain() for Unicode// // PURPOSE : This is the entry point for the program. This function// contains sample code demonstrating how to use the// RegFind*() functions implemented below.// // PARAMETERS: None// // RETURN VALUE: None// //**********************************************************************void _tmain( void ) { DWORD dwFilter; LONG lResult; HKEY hKey; char ch; HANDLE hChange = NULL; BOOL bContinue = TRUE; REG_CHANGE_DATA rcd; // open the key to be monitored lResult = RegOpenKeyEx( MONITOR_TOPKEY, MONITOR_SUBKEY, 0, KEY_READ, &hKey ); if ( lResult != ERROR_SUCCESS ) DisplayError( "RegOpenKeyEx()", lResult ); __try { // filter for all registry changes dwFilter = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_SECURITY; while ( bContinue ) { _tprintf( TEXT("'f' FindFirst; 'n' FindNext; 'q' Quit --> ") ); ch = _getche(); _tprintf( TEXT("/n") ); switch ( ch ) { case 'f': case 'F': // FindFirst // close old handle, if it exists if ( hChange ) RegFindCloseChange( hChange ); hChange = RegFindFirstChange( hKey, TRUE, dwFilter, &rcd ); if ( hChange == NULL ) DisplayError( TEXT("RegFindFirstChange()"), GetLastError() ); break; case 'n': case 'N': // FindNext if ( !RegFindNextChange( hChange, &rcd ) ) DisplayError( TEXT("RegFindNextChange()"), GetLastError() ); break; case 'q': case 'Q': // Quit __leave; break; } // wait on the handle, if it exists if ( hChange ) { _tprintf( TEXT("Waiting.../n") ); WaitForSingleObject( hChange, INFINITE ); _tprintf( TEXT("Registry change notification received/n") ); } } } __finally { // close change handle, if it exists if ( hChange ) RegFindCloseChange( hChange ); // close key handle RegCloseKey( hKey ); }}//**********************************************************************// // RegFindFirstChange()// // PURPOSE: This function begins a registry change notification // cycle. It will never return a handle that is already // signaled due to interim change notifications.// // After a call to RegFindFirstChange(), a call to// RegFindNextChange() ensures that interim // notifications are not missed.// // Since this routine allocates resources, it is // important that each call is matched up with a // corresponding RegFindCloseChange() call to free the // resources.// // PARAMETERS: hKey - handle to the key to watch// // bWatchSubtree - indicates whether or not to receive// notifications for changes in subkeys// // dwNotifyFilter - identifies which changes should cause// notifications to occur// // lprcd - pointer to a REG_CHANGE_DATA structure used// to cycle through the changes// // RETURN VALUE: If the function succeeds, a wait able handle is // returned. If it fails, NULL is returned and a call to// GetLastError() identifies why it failed.// //**********************************************************************HANDLE RegFindFirstChange( HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, LPREG_CHANGE_DATA lprcd ) { LONG lResult; HANDLE hChange; lprcd->hKey = hKey; lprcd->bWatchSubtree = bWatchSubtree; lprcd->dwNotifyFilter = dwNotifyFilter; // create event to be signaled when changes occur hChange = CreateEvent( NULL, TRUE, FALSE, NULL ); // request registry change notifications lResult = RegNotifyChangeKeyValue( lprcd->hKey, lprcd->bWatchSubtree, lprcd->dwNotifyFilter, hChange, TRUE ); if ( lResult != ERROR_SUCCESS ) { SetLastError( lResult ); return NULL; } // It is possible that this key handle has been used to receive // registry notifications already. Thus, you will wait with a timeout // of zero to clear interim notifications that might have occurred if ( WaitForSingleObject( hChange, 0 ) == WAIT_OBJECT_0 ) { // There were some interim changes; they are cleared now, but // you must call the API again to request future notifications lResult = RegNotifyChangeKeyValue( lprcd->hKey, lprcd->bWatchSubtree, lprcd->dwNotifyFilter, hChange, TRUE ); if ( lResult != ERROR_SUCCESS ) { SetLastError( lResult ); return NULL; } } return hChange;}//**********************************************************************// // RegFindNextChange()// // PURPOSE: This function queues the next registry change // notification in a cycle. It must be preceded by a // call to RegFindFirstChange().// // After calling this function, the handle returned by // RegFindFirstChange() can be waited on again to get // the next change notification. Using these functions // in this manner, all interim change notifications will// be caught.// // PARAMETERS: lprcd - pointer to the same REG_CHANGE_DATA structure// that was initialized with RegFindFirstChange()// // RETURN VALUE: If the function succeeds, it returns TRUE. If it // fails, it returns FALSE and a call to GetLastError() // identifies why it failed.// //**********************************************************************BOOL RegFindNextChange( HANDLE hChange, LPREG_CHANGE_DATA lprcd ) { LONG lResult; // reset the event so the handle can be waited on again if ( !ResetEvent( hChange ) ) return FALSE; // If you call this function, you want to catch interim changes, // so simply call the API again. lResult = RegNotifyChangeKeyValue( lprcd->hKey, lprcd->bWatchSubtree, lprcd->dwNotifyFilter, hChange, TRUE ); if ( lResult != ERROR_SUCCESS ) { SetLastError( lResult ); return FALSE; } return TRUE;}//**********************************************************************// // RegFindCloseChange()// // PURPOSE: This function frees the resources allocated by a call// to RegFindFirstChange().// // PARAMETERS: hChange - the waitable handle returned from // RegFindFirstChange()// // RETURN VALUE: Always TRUE// //**********************************************************************BOOL RegFindCloseChange( HANDLE hChange ) { // free event if ( hChange ) { CloseHandle( hChange ); hChange = NULL; } return TRUE;}//**********************************************************************// // DisplayError()// // PURPOSE : This is a helper function to display an error message // and exit the process if a function in _tmain() fails.// // PARAMETERS: szAPI - the name of the function that failed// // dwError - the Win32 error code indicating why the// function failed// // RETURN VALUE: None// //**********************************************************************void DisplayError( LPTSTR szAPI, DWORD dwError ) { LPTSTR lpBuffer = NULL; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpBuffer, 0, NULL ); _tprintf( TEXT("%s failed:/n"), szAPI ); _tprintf( TEXT(" error code = %u/n"), dwError ); _tprintf( TEXT(" message = %s/n"), lpBuffer ); LocalFree( lpBuffer ); ExitProcess(0);}
http://www.blogbus.com/public/tb.php/1459042/24389391/d1b2d856a57f824b366f60fb09f9d3f6