Home | Chi sono | Contattami
 

Progr. lineare

Delphi
 
Componenti
  Database
 
Miei articoli

Windows

Miei articoli 

 

Enumerare le chiavi di registro modificate in un dato intervallo di tempo


Il programma che vado ad esporre in questo articolo nasce tempo addietro, il giorno in cui mi venne in mente di determinare quali fossero le voci di registro che definiscono in Windows XP l' utilizzo del menł di avvio proprio di Windows XP oppure l' utilizzo di quello classico (stile windows 2000 tanto per intenderci). Utilizzando il Registry Monitor di marca Sysinternals, venivo sommerso da un mare di modifiche ... in pratica non era quella la strada. Allora ho pensato ad un programmino per enumerare tutte le modifiche effettuate sul registro in un determinato intervallo. Fortunatamente le api win32 relative alla gestione del registro consentono la determinazione della data e ora di ultima modifica di ogni chiave di registro. Passiamo ai paragrafi successivi per esaminare i dettagli dell'implementazione.

1. RegQueryInfoKey

L'api win32 RegQueryInfoKey implementata in advapi32.dll , consente di ottenere informazioni relative ad un determinata chiave di registro. Di seguito la definizione

PFileTime = ^TFileTime; TFileTime = record dwLowDateTime: Cardinal; dwHighDateTime: Cardinal; end; function RegQueryInfoKey(hKey: Cardinal; lpClass: PChar; lpcbClass: PCardinal; lpReserved: Pointer; lpcSubKeys: PCardinal; lpcbMaxSubKeyLen: PCardinal; lpcbMaxClassLen: PCardinal; lpcValues: PCardinal; lpcbMaxValueNameLen: PCardinal; lpcbMaxValueLen: PCardinal; lpcbSecurityDescriptor: PCardinal; lpftLastWriteTime: PFileTime ): Integer; stdcall;

Analizziamo i singoli parametri:

  • hKey:[input] handle alla chiave di registro che si vuole esaminare; tale handle puņ essere un valore restituito dalle api win32 RegCreateKeyEx e RegOpenKeyEx (in tal caso bisogna aver specificato il diritto di accesso KEY_QUERY_VALUE) oppure puņ essere uno dei valori predefiniti che fanno riferimento alle "root" ossia: HKEY_CLASSES_ROOT ($80000000), HKEY_CURRENT_USER ($80000001), HKEY_LOCAL_MACHINE ($80000002), HKEY_USERS ($80000003), HKEY_PERFORMANCE_DATA ($80000004), HKEY_CURRENT_CONFIG ($80000005),
  • lpClass: [output] si puņ ignorare
  • lpcbClass: [input, output] fa riferimento a lpClass e quindi ignorabile
  • lpReserved: deve essere nil obbligatoriamente
  • lpcSubKeys: [output] riceve il numero di sotto-chiavi della chiave in esame
  • lpcbMaxSubKeyLen: [output] riceve la lunghezza massima (senza contare il carattere di terminazione) dei nomi delle sotto-chiavi della chiave in esame
  • lpcbMaxClassLen: [output]  si puņ ignorare
  • lpcValues: [output] riceve il numero dei valori associati con la chiave in esame
  • lpcbMaxValueNameLen: [output] riceve la lunghezza massima (senza contare il carattere di terminazione) dei nomi dei valori associati alla chiave in esame
  • lpcbMaxValueLen: [output] riceve la dimensione massima dei dati dei valori associati alla chiave in esame
  • lpcbSecurityDescriptor: [output] riceve la dimensione del security descriptor della chiave: si puņ ignorare
  • lpftLastWriteTime: [output] riceve la data/ora di ultima scrittura (quello che ci interessa principalmente in questo articolo)

In caso di successo la funzione restituisce 0; in caso differente si puņ usare GetLastError per maggiori informazioni sull'errore che si č verificato.

2. GetKeyInfo

GetKeyInfo č un metodo della classe TRegistry implementata da Delphi nella unit Registry.pas. In pratica č un wrapper all'api RegQueryInfoKey discussa precedentemente. Di seguito la dichiarazione

type TRegKeyInfo = record NumSubKeys: Integer; //numero di sottochiavi MaxSubKeyLen: Integer; //lunghezza massima dei nomi delle sottochiavi NumValues: Integer; //numero di valori MaxValueLen: Integer; //lunghezza massima dei nomi dei valori MaxDataLen: Integer; //dimensione massima dei dati dei valori FileTime: TFileTime; //data/ora di ultima scrittura end; function TRegistry.GetKeyInfo(var Value: TRegKeyInfo ): Boolean;

Useremo questo metodo per estrarre la data/ora di ultima modifica di una chiave di registro.

3. Conversione da TFileTime a TDateTime

Per ottenere un valore di tipo TDateTime dal valore TregKeyInfo.FileTime (di tipo TFileTime) ci serviremo delle seguenti 2 funzioni di supporto:

function DateTimeToLocalDateTime(dt: TDateTime): TDateTime; var TimeZoneInfo: TTimeZoneInformation; begin case GetTimeZoneInformation(TimeZoneInfo) of TIME_ZONE_ID_STANDARD: Result := dt - (TimeZoneInfo.Bias / 60 / 24); TIME_ZONE_ID_DAYLIGHT: Result := dt - ((TimeZoneInfo.Bias + TimeZoneInfo.DaylightBias) / 60 / 24); else Result := 0; end; end; function FileTimeToDateTime(ft: TFileTime): TDateTime; var SystemTime: TSystemTime; FileTime: TFileTime; begin if FileTimeToLocalFileTime(ft, FileTime) then begin FileTimeToSystemTime(ft, SystemTime); Result := SystemTimeToDateTime(SystemTime); end; end;

Di seguito il codice per la conversione

//conversione da TFileTime a TDateTime var FileTime: TFileTime; RegDate: TDateTime; ... begin ... RegDate := FileTimeToDateTime(FileTime); RegDate := DateTimeToLocalDateTime(RegDate); ... end;

Chiaramente per convertire un TDateTime nella stringa corrispondente possiamo usare la nota TDateTimeToStr

4. Enumerazione delle chiavi di registro a partire da una chiave

Siamo finalmente arrivati alla procedura ricorsiva che enumera le chiavi di registro a partire da una chiave data e per ognuna di esse chiama la GetKeyInfo per verificare se la data/ora di ultima modifica rientra nell'intervallo prefissato.

var Inizio, Fine: TDateTime; //estremi dell'intervallo di riferimento procedure EnumAllKeys(hkey: THandle; //handle alla chiave KeyName: string //nome della chiave ); var l: TStringList; n: Integer; KeyName_: string; RegDate: TDateTime; RegKeyInfo: TRegKeyInfo; begin KeyName_ := KeyName; with TRegistry.Create do try RootKey := hkey; OpenKey(EmptyStr, False); l := TStringList.Create; try GetKeynames(l); CloseKey; for n := 0 to l.Count - 1 do begin if OpenKey(l[n], False) then begin if (l[n] = '') then begin CloseKey; continue; end; GetKeyInfo(RegKeyInfo); with RegKeyInfo do begin RegDate := FileTimeToDateTime(FileTime); RegDate := DateTimeToLocalDateTime(RegDate); end; if (RegDate <= Fine) and (RegDate >= Inizio) then begin //ho trovato una chiave la cui data/ora di ultima modifica //rientra nel'intervallo specificato FrmMain.Memo1.Lines.Add(DateTimeToStr(RegDate) + ' --- ' + KeyName_ + '\' + l[n]); end; EnumAllKeys(CurrentKey, KeyName_ + '\' + l[n]); CloseKey; end; end; finally l.Free end; finally Free; end; end;

5. Esempi

Analisi nel contesto dell'utente corrente:

EnumAllKeys(HKEY_CURRENT_USER, 'HKey_Current_User');

Analisi a livello di macchina:

EnumAllKeys(HKEY_LOCAL_MACHINE, 'HKey_Local_Machine');

6. Qualcosina per finire

Behh, abbiamo visto come trovare le chiavi di registro modificate in un determinato intervallo. A questo punto quindi puņ diventare divertente salvarsi il ramo di registro che ci interessa, fare determinate operazioni, trovare poi le chiavi che sono state modificate e fare dei bei confronti "prima"-"dopo". Ahh ... dimenticavo, ero partito dicendo che il motivo di tutti sti ragionamenti era quello di determinare le parti di registro che regolano il tipo di menu in Windows Xp (classico o nuovo): ebbene ora abbiamo la soluzione

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer] "ShellState"=hex:24,00,00,00,3a,08,01,00,00,00,00,00,00,00,00,00,00,00,00,00,\ 01,00,00,00,0d,00,00,00,00,00,00,00,01,00,00,00

Occorre considerare il quart'ultimo elemento:

03 = avvio di default
01 = avvio classico

Dare un'occhiata anche all'articolo Personalizzazione della Shell di Windows da registro per ulteriori approfondimenti al riguardo.

RegEnum

 

 
 
Your Ad Here