RegNotifyChangeKeyValue 函数 (winreg.h)

通知调用方对指定注册表项的属性或内容的更改。

语法

LSTATUS RegNotifyChangeKeyValue(
  [in]           HKEY   hKey,
  [in]           BOOL   bWatchSubtree,
  [in]           DWORD  dwNotifyFilter,
  [in, optional] HANDLE hEvent,
  [in]           BOOL   fAsynchronous
);

参数

[in] hKey

打开的注册表项的句柄。 此句柄由 RegCreateKeyExRegOpenKeyEx 函数返回。 也可以是以下 预定义键之一:

HKEY_CLASSES_ROOTHKEY_CURRENT_CONFIGHKEY_CURRENT_USERHKEY_LOCAL_MACHINEHKEY_USERS 此参数必须是本地句柄。 如果使用远程句柄调用 RegNotifyChangeKeyValue ,则返回ERROR_INVALID_HANDLE。

密钥必须已使用KEY_NOTIFY访问权限打开。 有关详细信息,请参阅 注册表项安全和访问权限

[in] bWatchSubtree

如果此参数为 TRUE,则函数将报告指定键及其子项中的更改。 如果参数为 FALSE,则函数仅报告指定键中的更改。

[in] dwNotifyFilter

一个 值,该值指示应报告的更改。 此参数可使用以下一个或多个值。

含义
REG_NOTIFY_CHANGE_NAME
0x00000001L
通知调用方是添加还是删除了子项。
REG_NOTIFY_CHANGE_ATTRIBUTES
0x00000002L
向调用方通知项属性(例如安全描述符信息)的更改。
REG_NOTIFY_CHANGE_LAST_SET
0x00000004L
向调用方通知项值的更改。 这包括添加或删除值,或更改现有值。
REG_NOTIFY_CHANGE_SECURITY
0x00000008L
向调用方通知项的安全描述符的更改。
REG_NOTIFY_THREAD_AGNOSTIC
0x10000000L
指示注册的生存期不得绑定到发出 RegNotifyChangeKeyValue 调用的线程的生存期。
注意 此标志值仅在 Windows 8 及更高版本中受支持。
 

[in, optional] hEvent

事件的句柄。 如果 fAsynchronous 参数为 TRUE,则函数将立即返回 ,并通过发出此事件信号来报告更改。 如果 fAsynchronousFALSE,则忽略 hEvent

[in] fAsynchronous

如果此参数为 TRUE,则函数将立即返回并通过向指定事件发出信号来报告更改。 如果此参数为 FALSE,则函数在发生更改之前不会返回 。

如果 hEvent 未指定有效的事件, 则 fAsynchronous 参数不能为 TRUE

返回值

如果函数成功,则返回值为 ERROR_SUCCESS。

如果函数失败,则返回值为 Winerror.h 中定义的非零错误代码。 可以将 FormatMessage 函数与 FORMAT_MESSAGE_FROM_SYSTEM 标志结合使用来获取错误的常规说明。

注解

此函数检测单个更改。 调用方收到通知事件后,应再次调用 函数以接收下一个通知。

注意 在 Windows NT、Windows 2000 和 Windows XP 上,调用特定键句柄的 RegNotifyChangeKeyValue 会导致只要密钥句柄有效,更改通知就继续发生。 这会导致对 RegNotifyChangeKeyValue 的第二次调用立即返回,前提是在第一次和第二次调用之间的过渡期间发生了任何更改。 如果异步使用 API,则发生任何临时更改时,将立即向传递的事件句柄发出信号。
 
此函数不能用于检测因使用 RegRestoreKey 函数而导致的注册表更改。

如果指定的键已关闭,则会向事件发出信号。 这意味着,应用程序不应依赖于从事件的等待操作返回后打开的密钥。

Windows 8 中引入 的 REG_NOTIFY_THREAD_AGNOSTIC 标志允许对 ThreadPool 线程使用 RegNotifyChangeKeyValue

如果调用 RegNotifyChangeKeyValue 的线程退出,则会发出事件信号。 若要继续监视键值的其他更改,请再次从另一个线程调用 RegNotifyChangeKeyValue

除了设置了 REG_NOTIFY_THREAD_AGNOSTICRegNotifyChangeKeyValue 调用之外,必须在持久性线程上调用此函数。 如果调用线程来自线程池且不是永久性的,则每次线程终止时都会发出事件信号,而不仅仅是在注册表发生更改时发出信号。 若要确保结果准确,请使用 SetThreadpoolCallbackPersistent 函数在持久线程中运行线程池工作,或使用 CreateThread 函数创建自己的线程。 (对于原始线程池 API,请使用 QueueUserWorkItem 函数指定WT_EXECUTEINPERSISTENTTHREAD。)

不应多次调用此函数,其 hKey 值相同,但 bWatchSubtreedwNotifyFilter 参数的值不同。 函数将成功,但将忽略更改。 若要更改
watch参数,必须首先通过调用 RegCloseKey 关闭键句柄,通过调用 RegOpenKeyEx 重新打开密钥句柄,然后使用新参数调用 RegNotifyChangeKeyValue

每次进程使用相同的参数集调用 RegNotifyChangeKeyValue 时,它都会建立另一个等待操作,从而造成资源泄漏。 因此,检查,在上一个等待操作完成之前,不会使用相同的参数调用 RegNotifyChangeKeyValue

若要更详细地监视注册表操作,请参阅 注册表

Windows XP/2000: 为特定键句柄调用 RegNotifyChangeKeyValue 时,只要密钥句柄有效,更改通知就会出现。 这会导致第二次调用 RegNotifyChangeKeyValue 立即返回,前提是第一次调用和第二次调用之间发生任何更改。 如果异步使用函数,则在此期间发生任何更改时,将立即向传递的事件句柄发出信号。

示例

以下程序演示如何使用 RegNotifyChangeKeyValue

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

//void main(int argc, char *argv[])
void __cdecl _tmain(int argc, TCHAR *argv[])
{
   DWORD  dwFilter = REG_NOTIFY_CHANGE_NAME |
                     REG_NOTIFY_CHANGE_ATTRIBUTES |
                     REG_NOTIFY_CHANGE_LAST_SET |
                     REG_NOTIFY_CHANGE_SECURITY; 

   HANDLE hEvent;
   HKEY   hMainKey;
   HKEY   hKey;
   LONG   lErrorCode;

   // Display the usage error message.
   if (argc != 3) 
   {
      _tprintf(TEXT("Usage: notify [HKLM|HKU|HKCU|HKCR|HCC] [<subkey>]\n"));
      return;
   }

   // Convert parameters to appropriate handles.
   if (_tcscmp(TEXT("HKLM"), argv[1]) == 0) hMainKey=HKEY_LOCAL_MACHINE;
   else if(_tcscmp(TEXT("HKU"), argv[1]) == 0) hMainKey=HKEY_USERS;
   else if(_tcscmp(TEXT("HKCU"), argv[1]) == 0) hMainKey=HKEY_CURRENT_USER;
   else if(_tcscmp(TEXT("HKCR"), argv[1]) == 0) hMainKey=HKEY_CLASSES_ROOT;
   else if(_tcscmp(TEXT("HCC"), argv[1]) == 0) hMainKey=HKEY_CURRENT_CONFIG;
   else 
   {
      _tprintf(TEXT("Usage: notify [HKLM|HKU|HKCU|HKCR|HCC] [<subkey>]\n"));
      return;
   }

   // Open a key.
    lErrorCode = RegOpenKeyEx(hMainKey, argv[2], 0, KEY_NOTIFY, &hKey);
   if (lErrorCode != ERROR_SUCCESS)
   {
      _tprintf(TEXT("Error in RegOpenKeyEx (%d).\n"), lErrorCode);
      return;
   }

   // Create an event.
   hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
   if (hEvent == NULL)
   {
      _tprintf(TEXT("Error in CreateEvent (%d).\n"), GetLastError());
      return;
   }

   // Watch the registry key for a change of value.
   lErrorCode = RegNotifyChangeKeyValue(hKey, 
                                        TRUE, 
                                        dwFilter, 
                                        hEvent, 
                                        TRUE);
   if (lErrorCode != ERROR_SUCCESS)
   {
      _tprintf(TEXT("Error in RegNotifyChangeKeyValue (%d).\n"), lErrorCode);
      return;
   }

   // Wait for an event to occur.
   _tprintf(TEXT("Waiting for a change in the specified key...\n"));
   if (WaitForSingleObject(hEvent, INFINITE) == WAIT_FAILED)
   {
      _tprintf(TEXT("Error in WaitForSingleObject (%d).\n"), GetLastError());
      return;
   }
   else _tprintf(TEXT("\nChange has occurred.\n"));

   // Close the key.
   lErrorCode = RegCloseKey(hKey);
   if (lErrorCode != ERROR_SUCCESS)
   {
      _tprintf(TEXT("Error in RegCloseKey (%d).\n"), GetLastError());
      return;
   }
   
   // Close the handle.
   if (!CloseHandle(hEvent))
   {
      _tprintf(TEXT("Error in CloseHandle.\n"));
      return;
   }
}

要求

   
最低受支持的客户端 Windows 2000 Professional [仅限桌面应用]
最低受支持的服务器 Windows 2000 Server [仅限桌面应用]
目标平台 Windows
标头 winreg.h (包括 Windows.h)
Library Advapi32.lib
DLL Advapi32.dll

另请参阅

RegCloseKey

RegDeleteKey

RegEnumKeyEx

RegEnumValue

RegQueryInfoKey

RegQueryValueEx

注册表函数