声明: この記事を転載する CSDN 以外のグループまたは個人は、出典と著者を明示する必要があります。
Delphi に付属の TRegistry クラスは、レジストリの基本操作のみを実装できます。レジストリの変更をリアルタイムで監視したり、レジストリ内の特定のキーの下にあるすべてのサブキーをスキャンしたりする場合、TRegistry クラスは無力です。私は長い間 SDK をかじっていましたが、ついに Delphi によるレジストリの監視とスキャンに気づきました。それを自分だけのものにしておく勇気がなかったので、大多数の Delphi 愛好家に捧げました。
レジストリ関連項目の変更を監視するには、API: RegNotifyChangeKeyValue が必要です。
LONG RegNotifyChangeKeyValue(
HKEY hKey, // 監視する項目のハンドル
BOOL bWatchSubtree, // この項目のサブキーを監視するかどうか
DWord dwNotifyFilter, // 監視する変更内容
HANDLE hEvent, // レジストリ変更イベントを受け入れるイベント オブジェクト ハンドル
BOOL fAsynchronous // レジストリ変更前またはレジストリ変更後のレポート
);
上記の hEvent は、レジストリ変更イベントを受け入れるイベント オブジェクト ハンドルであることに注意してください。システム イベント オブジェクトを作成するには、API: CreateEvent を使用する必要があります。
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES 構造体
BOOL bManualReset, // 自動的にリセットするかどうか
BOOL bInitialState, // 初期状態を設定するかどうか
LPCTSTR lpName //イベントオブジェクトの名前
);
新しいプロジェクトを作成し、ListBox と 2 つのボタンを追加します。
//まずレジストリを監視する例を書きます
//HKEY_CURRENT_USER/Software 項目の下にあるすべてのサブキーを監視します
手順 TForm1.Button1Click(送信者: TObject);
変数
hNotify: THandle;
hKeyx:HKEY;
dwRes: DWORD;
始める
hNotify := CreateEvent( nil, //SECURITY_ATTRIBUTES 構造体を使用しないでください
FALSE, //自動的にリセットしません
TRUE, //初期状態を設定する
'RegistryNotify' // イベント オブジェクトの名前
);
hNotify = 0の場合
始める
Showmessage('イベントの作成に失敗しました。');
出口;
終わり;
if RegOpenKeyEx(HKEY_CURRENT_USER, //キーをたどる
'ソフトウェア', //サブキー
0, //予約済み
KEY_NOTIFY, //監視用
hKeyx //ハンドルを保存
) <> ERROR_SUCCESS その後
始める
CloseHandle( hNotify );
Showmessage('RegOpenKeyEx が失敗しました。');
出口;
終わり;
if RegNotifyChangeKeyValue( hKeyx, //サブキーハンドルを監視する
TRUE, //この項目のサブキーを監視します
REG_NOTIFY_CHANGE_NAME または REG_NOTIFY_CHANGE_LAST_SET、
hNotify, //レジストリ変更イベントを受け入れるイベント オブジェクト ハンドル
TRUE //レジストリ変更前のレポート
) <> ERROR_SUCCESS その後
始める
CloseHandle( hNotify );
RegCloseKey( hKeyx );
Showmessage('RegNotifyChangeKeyValue が失敗しました');
出口;
終わり;
dwRes := WaitForSingleObject( hNotify, 60 * 1000 ); // 1 分間監視します
dwRes = 0の場合
Showmessage( 'レジストリが変更されます。' );
CloseHandle( hNotify );
RegCloseKey( hKeyx );
終わり;
API: WaitForSingleObject は、レジストリ変更イベントが発生するかタイムアウトするまで返されないことに注意してください。この期間中、プログラムは応答を失います。解決策は、新しいスレッドを作成し、その新しいスレッドでレジストリを監視することです。
レジストリのスキャンには、他の 2 つの API (RegEnumKey と RegEnumValue) が使用されます。
LONG RegEnumKey(
HKEY hKey, // スキャンするレジストリ項目のハンドル
DWORD dwIndex,//スキャンするサブキーのシリアル番号
LPTSTR lpName,//スキャンするサブキー名
LPDWORD lpcbName, // スキャンされるサブキー名がスペースを占有しています
);
この関数の使用方法は、まず dwIndex に 0 を割り当て、RegEnumKey を呼び出し、次に Inc(dwIndex) を呼び出し、戻り値が ERROR_NO_MORE_ITEMS (サブ項目がなくなったことを示す) になるまで RegEnumKey を呼び出します。
//レジストリのスキャン例
//HKEY_CURRENT_USER/Software の下の 1 レベルのサブ項目を列挙する方法のみを示します。
プロシージャ TForm1.Button2Click(送信者: TObject);
変数
buf : char の配列 [0..255]。
iRes : 整数;
hKeyx:HKEY;
dwIndex、dwSize: DWORD;
始める
if RegOpenKeyEx( HKEY_CURRENT_USER, 'ソフトウェア', 0, KEY_READ または
KEY_ENUMERATE_SUB_KEYS、hKeyx ) <> ERROR_SUCCESS その後
始める
Showmessage('RegOpenKeyEx が失敗しました。');
出口;
終わり;
dwインデックス := 0;
繰り返す
dwサイズ:= 255;
iRes := RegEnumKey( hKeyx, dwIndex, buf, dwSize );
iRes = ERROR_NO_MORE_ITEMS の場合
壊す
それ以外の場合、iRes = ERROR_SUCCESS の場合
始める
Listbox1.Items.Add(buf);
Inc(dwIndex);
終わり;
iRes <> ERROR_SUCCESS まで;
RegCloseKey( hKeyx );
終わり;