聲明:CSDN以外的任合團(tuán)體和個(gè)人轉(zhuǎn)載本文必須注明出處和作者。
Delphi自帶的TRegistry類(lèi)只能實(shí)現(xiàn)注冊(cè)表的基本操作,如果我們要實(shí)時(shí)監(jiān)視注冊(cè)表的變化或者掃描注冊(cè)表特定項(xiàng)下的所有子項(xiàng),TRegistry類(lèi)就無(wú)能為力了。我啃了半天SDK,終于實(shí)現(xiàn)了Delphi對(duì)注冊(cè)表的監(jiān)視與掃描,不敢獨(dú)享,拿來(lái)獻(xiàn)給廣大的Delphi愛(ài)好者。
監(jiān)視注冊(cè)表相關(guān)項(xiàng)的改變要用到一個(gè)API:RegNotifyChangeKeyValue。
LONG RegNotifyChangeKeyValue(
HKEY hKey, // 要監(jiān)視的一個(gè)項(xiàng)的句柄
BOOL bWatchSubtree, // 是否監(jiān)視此項(xiàng)的子鍵
DWord dwNotifyFilter, // 監(jiān)視哪些變化
HANDLE hEvent, // 接受注冊(cè)表變化事件的事件對(duì)象句柄
BOOL fAsynchronous // 注冊(cè)表變化前報(bào)告還是注冊(cè)表變化后才報(bào)告
);
注意上面的hEvent是接受注冊(cè)表變化事件的事件對(duì)象句柄,我們要用API:CreateEvent來(lái)創(chuàng)建一個(gè)系統(tǒng)事件對(duì)象。
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES結(jié)構(gòu)
BOOL bManualReset, // 是否自動(dòng)重置
BOOL bInitialState, // 是否設(shè)置初始狀態(tài)
LPCTSTR lpName // 事件對(duì)象的名稱
);
新建一個(gè)工程,添加一個(gè)ListBox,兩個(gè)Button。
//先寫(xiě)個(gè)監(jiān)視注冊(cè)表的例子
//監(jiān)視HKEY_CURRENT_USER/Software項(xiàng)下所有子鍵
PRocedure TForm1.Button1Click(Sender: TObject);
var
hNotify : THandle;
hKeyx : HKEY;
dwRes : DWORD;
begin
hNotify := CreateEvent( nil, //不使用SECURITY_ATTRIBUTES結(jié)構(gòu)
FALSE, //不自動(dòng)重置
TRUE, //設(shè)置初始狀態(tài)
'RegistryNotify' //事件對(duì)象的名稱
);
if hNotify = 0 then
begin
Showmessage('CreateEvent failed.');
exit;
end;
if RegOpenKeyEx( HKEY_CURRENT_USER, //跟鍵
'Software', //子鍵
0, //reserved
KEY_NOTIFY, //監(jiān)視用
hKeyx //保存句柄
) <> ERROR_SUCCESS then
begin
CloseHandle( hNotify );
Showmessage('RegOpenKeyEx failed.');
exit;
end;
if RegNotifyChangeKeyValue( hKeyx, //監(jiān)視子鍵句柄
TRUE, //監(jiān)視此項(xiàng)的子鍵
REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_LAST_SET,
hNotify, //接受注冊(cè)表變化事件的事件對(duì)象句柄
TRUE //注冊(cè)表變化前報(bào)告
) <> ERROR_SUCCESS then
begin
CloseHandle( hNotify );
RegCloseKey( hKeyx );
Showmessage('RegNotifyChangeKeyValue failed');
exit;
end;
dwRes := WaitForSingleObject( hNotify, 60 * 1000 ); //監(jiān)視一分鐘
if dwRes = 0 then
Showmessage( 'Registry will be changed.' );
CloseHandle( hNotify );
RegCloseKey( hKeyx );
end;
要注意的是,API: WaitForSingleObject要等到注冊(cè)表變化事件發(fā)生或者超時(shí)才會(huì)返回,在此期間我們的程序?qū)⑹ロ憫?yīng)。解決的辦法是新建一個(gè)線程,在新線程中監(jiān)視注冊(cè)表。
對(duì)注冊(cè)表進(jìn)行掃描要用到另外兩個(gè)API: RegEnumKey和RegEnumValue。
LONG RegEnumKey(
HKEY hKey, // 要掃描的注冊(cè)表項(xiàng)目句柄
DWORD dwIndex, // 要掃描的subkey序號(hào)
LPTSTR lpName, // 要掃描的subkey名稱
LPDWORD lpcbName, // 要掃描的subkey名稱占用空間
);
此函數(shù)的使用方法是: 首先給dwIndex賦值0, 調(diào)用RegEnumKey; 然后Inc(dwIndex), 再調(diào)用RegEnumKey,直到返回值為ERROR_NO_MORE_ITEMS,表示沒(méi)有更多的子項(xiàng)了。
//掃描注冊(cè)表的例子
//只演示了如何枚舉HKEY_CURRENT_USER/Software下的一層子項(xiàng)
procedure TForm1.Button2Click(Sender: TObject);
var
buf : array [0..255] of char;
iRes : integer;
hKeyx : HKEY;
dwIndex, dwSize : DWORD;
begin
if RegOpenKeyEx( HKEY_CURRENT_USER, 'Software', 0, KEY_READ or
KEY_ENUMERATE_SUB_KEYS, hKeyx ) <> ERROR_SUCCESS then
begin
Showmessage('RegOpenKeyEx failed.');
exit;
end;
dwIndex := 0;
repeat
dwSize := 255;
iRes := RegEnumKey( hKeyx, dwIndex, buf, dwSize );
if iRes = ERROR_NO_MORE_ITEMS then
break
else if iRes = ERROR_SUCCESS then
begin
Listbox1.Items.Add( buf );
Inc( dwIndex );
end;
until iRes <> ERROR_SUCCESS;
RegCloseKey( hKeyx );
end;
|
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注