Delphi實現對註冊表的監視和掃描

 
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,兩個Button。

//先寫個監視註冊表的例子
//監視HKEY_CURRENT_USER/Software項下所有子鍵
procedure TForm1.Button1Click(Sender: TObject);
var
hNotify : THandle;
hKeyx : HKEY;
dwRes : DWORD;
begin
hNotify := CreateEvent( nil, //不使用SECURITY_ATTRIBUTES結構
FALSE, //不自動重置
TRUE, //設置初始狀態
''RegistryNotify'' //事件對象的名稱
);

if hNotify = 0 then
begin
Showmessage(''CreateEvent failed.'');
exit;
end;

if RegOpenKeyEx( HKEY_CURRENT_USER, //跟鍵
''Software'', //子鍵
0, //reserved
KEY_NOTIFY, //監視用
hKeyx //保存句柄
) <> ERROR_SUCCESS then
begin
CloseHandle( hNotify );
Showmessage(''RegOpenKeyEx failed.'');
exit;
end;

if RegNotifyChangeKeyValue( hKeyx, //監視子鍵句柄
TRUE, //監視此項的子鍵
REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_LAST_SET,
hNotify, //接受註冊表變化事件的事件對象句柄
TRUE //註冊表變化前報告
) <> ERROR_SUCCESS then
begin
CloseHandle( hNotify );
RegCloseKey( hKeyx );
Showmessage(''RegNotifyChangeKeyValue failed'');
exit;
end;

dwRes := WaitForSingleObject( hNotify, 60 * 1000 ); //監視一分鐘
if dwRes = 0 then
Showmessage( ''Registry will be changed.'' );

CloseHandle( hNotify );
RegCloseKey( hKeyx );
end;

要注意的是,API: WaitForSingleObject要等到註冊表變化事件發生或者超時纔會返回,在此期間我們的程序將失去響應。解決的辦法是新建一個線程,在新線程中監視註冊表。

對註冊表進行掃描要用到另外兩個API: RegEnumKey和RegEnumValue。

LONG RegEnumKey(
HKEY hKey, // 要掃描的註冊表項目句柄
DWORD dwIndex, // 要掃描的subkey序號
LPTSTR lpName, // 要掃描的subkey名稱
LPDWORD lpcbName, // 要掃描的subkey名稱佔用空間
);

此函數的使用方法是: 首先給dwIndex賦值0, 調用RegEnumKey; 然後Inc(dwIndex), 再調用RegEnumKey,直到返回值爲ERROR_NO_MORE_ITEMS,表示沒有更多的子項了。

//掃描註冊表的例子
//只演示瞭如何枚舉HKEY_CURRENT_USER/Software下的一層子項
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;

 
發佈了50 篇原創文章 · 獲贊 7 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章