WIn32API レジストリの変更を検知する RegNotifyChangeKeyValue
レジストリキーの属性やエントリが変更されたことを検知するためには、RegNotifyChangeKeyValue関数を用いる。
RegNotifyChangeKeyValue関数は、レジストリが変更されたことをアプリケーションに通知してくれる。
RegNotifyChangeKeyValue関数のプロトタイプは、以下のようになっている。
LONG RegNotifyChangeKeyValue( HKEY hKey, // 監視するべきキーのハンドル BOOL bWatchSubtree, // サブキー監視オプション DWORD dwNotifyFilter, // 通知するべき変更 HANDLE hEvent, // 発生させるべきイベントのハンドル BOOL fAsynchronous // 変更の通知方法を示すフラグ );
dwNotifyFilterには、以下の値を組み合わせて通知すべき変更のタイプを指定する。
値 | 説明 |
REG_NOTIFY_CHANGE_NAME | サブキーの追加または削除が発生するときに通知する |
REG_NOTIFY_CHANGE_ATTRIBUTES | キーの属性の変更が発生した時に通知する |
REG_NOTIFY_CHANGE_LAST_SET | キー内のレジストリエントリの変更が生じた時に通知する |
REG_NOTIFY_CHANGE_SECURITY | キーのセキュリティ記述しの変更が発生した際に通知する |
RegNotifyChangeKeyValue関数を呼び出したあとに、WaitForSingleObjectでレジストリの変更通知を待機する。変更通知を受け取るとWaitForSingleObjectは制御を返し、ResetEventを呼び出すことにより、再び変更通知を待機する準備を行う。
#include <windows.h> #include <stdio.h> int main() { HANDLE hEvent = NULL; HKEY hKey = NULL; hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("RegistryNotificationEvent")); if (hEvent == NULL) { puts("CreateEvent error"); goto EXIT_FUNC; } //レジストリの変更通知を受けるためにはKEY_NOTIFYアクセス属性が必要となる if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Test"), 0, KEY_NOTIFY, &hKey) != ERROR_SUCCESS) { puts("RegOpenKeyEx error"); goto EXIT_FUNC; } for (;;) { //サブキーの追加、削除とキー内のレジストリエントリの変更を監視する if (RegNotifyChangeKeyValue(hKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, hEvent, TRUE) != ERROR_SUCCESS) { puts("RegNotifyChangeKeyValue error"); break; } //ここでブロッキング状態となる //レジストリの変更が生じるとWaitForSingleObjectが制御を返す if (::WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) { puts("Registry Change Notification"); } else { break; } if (ResetEvent(hEvent) == FALSE) { puts("ResetEvent error"); break; } } EXIT_FUNC: if (hKey != NULL) { RegCloseKey(hKey); } if (hEvent != NULL) { CloseHandle(hEvent); } puts("Exit"); return 0; }
イベントオブジェクトを使用しない場合は、RegNotifyChangeKeyValue関数でブロッキング状態になる。レジストリ変更通知を受け取るとRegNotifyChangeKeyValue関数は制御を返す。
#include <windows.h> #include <stdio.h> int main() { HKEY hKey = NULL; //レジストリの変更通知を受けるためにはKEY_NOTIFYアクセス属性が必要となる if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Test"), 0, KEY_NOTIFY, &hKey) != ERROR_SUCCESS) { puts("RegOpenKeyEx error"); goto EXIT_FUNC; } for (;;) { //ここでブロッキング状態となる //レジストリの変更通知を受け取ると、RegNotifyChangeKeyValueは制御を返す if (RegNotifyChangeKeyValue(hKey, TRUE, REG_NOTIFY_CHANGE_NAME|REG_NOTIFY_CHANGE_LAST_SET, NULL, FALSE) != ERROR_SUCCESS) { puts("RegNotifyChangeKeyValue error"); break; } puts("Registry Change Notification"); } EXIT_FUNC: if (hKey != NULL) { RegCloseKey(hKey); } puts("Exit"); return 0; }
上記のプログラム(イベントオブジェクトを使用する版/しない指版のいずれか)を実行して、監視対象のレジストリの属性やエントリ等の変更を行うと、変更の通知を受けることができる。