성명: 이 기사를 재인쇄하는 CSDN 이외의 모든 그룹이나 개인은 출처와 작성자를 표시해야 합니다.
Delphi와 함께 제공되는 TRegistry 클래스는 레지스트리의 기본 작업만 구현할 수 있습니다. 레지스트리의 변경 사항을 실시간으로 모니터링하거나 레지스트리의 특정 키 아래에 있는 모든 하위 키를 검색하려는 경우 TRegistry 클래스는 무력합니다. 나는 SDK를 오랫동안 갉아먹다가 마침내 델파이의 레지스트리 모니터링과 스캐닝을 깨달았습니다. 감히 혼자만 간직할 수 없어서 대다수의 델파이 매니아들에게 바쳤습니다.
레지스트리 관련 항목의 변경 사항을 모니터링하려면 RegNotifyChangeKeyValue라는 API가 필요합니다.
LONG RegNotifyChangeKey값(
HKEY hKey, // 모니터링할 항목에 대한 핸들
BOOL bWatchSubtree, // 이 항목의 하위 키를 모니터링할지 여부
DWord dwNotifyFilter, // 모니터링할 변경 사항
HANDLE hEvent, // 레지스트리 변경 이벤트를 받아들이는 이벤트 객체 핸들
BOOL fAsynchronous // 레지스트리 변경 전 또는 레지스트리 변경 후 보고
);
위의 hEvent는 레지스트리 변경 이벤트를 받아들이는 이벤트 개체 핸들입니다. 시스템 이벤트 개체를 생성하려면 CreateEvent API를 사용해야 합니다.
CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES 구조
BOOL bManualReset, // 자동 재설정 여부
BOOL bInitialState, // 초기 상태를 설정할지 여부
LPCTSTR lpName //이벤트 객체의 이름
);
새 프로젝트를 만들고 ListBox와 두 개의 버튼을 추가합니다.
//먼저 레지스트리를 모니터링하는 예제를 작성합니다.
//HKEY_CURRENT_USER/Software 항목 아래의 모든 하위 키를 모니터링합니다.
PROcedure TForm1.Button1Click(Sender: TObject);
var
h알림: 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는 레지스트리 변경 이벤트가 발생하거나 시간 초과될 때까지 반환되지 않습니다. 이 기간 동안 프로그램은 응답을 잃게 됩니다. 해결책은 새 스레드를 생성하고 새 스레드에서 레지스트리를 모니터링하는 것입니다.
레지스트리를 스캔하는 데는 RegEnumKey 및 RegEnumValue라는 두 가지 다른 API가 사용됩니다.
LONG RegEnumKey(
HKEY hKey, // 스캔할 레지스트리 항목 핸들
DWORD dwIndex,//스캔할 하위 키 일련번호
LPTSTR lpName,//스캔할 하위 키 이름
LPDWORD lpcbName, // 스캔할 하위 키 이름이 공간을 차지합니다.
);
이 함수를 사용하는 방법은 다음과 같습니다. 먼저 dwIndex에 0 값을 할당하고 RegEnumKey를 호출한 다음 Inc(dwIndex)를 호출한 다음 반환 값이 더 이상 하위 항목이 없음을 나타내는 ERROR_NO_MORE_ITEMS가 될 때까지 RegEnumKey를 호출합니다.
//레지스트리 스캔 예
//HKEY_CURRENT_USER/Software에서 한 수준의 하위 항목을 열거하는 방법만 보여줍니다.
절차 TForm1.Button2Click(Sender: TObject);
var
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;
반복하다
dwSize := 255;
iRes := RegEnumKey( hKeyx, dwIndex, buf, dwSize );
iRes = ERROR_NO_MORE_ITEMS인 경우
부서지다
그렇지 않으면 iRes = ERROR_SUCCESS인 경우
시작하다
Listbox1.Items.Add(buf);
Inc(dw인덱스);
끝;
iRes <> ERROR_SUCCESS까지;
RegCloseKey(hKeyx);
끝;