Programowanie w języku Delphi » Artykuły

Rejestry systemu Windows

Uwaga! Wersja skrócona.
Pełna, aktualna wersja tego artykułu znajduje się pod w artykule Rejestry i pliki INI.



W pierwszej kolejności należy odpowiedzieć czym jest rejestr Windows. Kliknij na menu Start, a następnie na pozycje Uruchom. W polu tekstowym wpisz "regedit". Otworzy się edytor rejestru. Zobaczysz tam ogromną ilość pozycji. W tym artykule te foldery będę nazywał kluczami, a pozycje w prawej części okna będę nazywał wartościami rejestru. No, ale nie odpowiedziałem na najważniejsze pytanie: czym jest rejestr? Co prawda Microsoft zaprzecza ale jest to ogromne źródło informacji o naszym systemie, zainstalowanych programach, konfiguracji itp. Manipulowanie rejestrem bez znajomości rzeczy grozi poważnymi konsekwencjami - złym działaniem programu, błędami albo nawet niemożnością uruchomienia systemu. Także programy, które instalujesz w swoim systemie wykorzystują rejestr Windows. Zapisują w nim swoją konfiguracje. Pomyśl, włączasz program, ustawiasz konfiguracje, zamykasz program i uruchamiasz go ponownie, a konfiguracja jest ustawiona tak samo! Gdzie program te ustawienia przechowuje? Albo w rejestrze, albo w plikach INI. Także Ty, w swoich programach możesz wykorzystać rejestr...

Klasa TRegistry


VCL udostępnia nam do tego celu bardzo wygodną w użyciu klasę - TRegistry. Naprawdę, tworzenie kluczy w rejestrze przy pomocy tej klasy jest rzeczą bardzo prostą. Na początek musisz do sekcji uses dodać w swoim programie moduł Registry. A teraz test - stworzenie nowego klucza. Ogólnie przyjętą regułą jest to, że klucze dla aplikacji zapisywane są w kluczu głównym HKEY_CURRENT_USER. My także będziemy tam zapisywali swoje dane.

procedure TMainForm.btnAcceptClick(Sender: TObject);
var
  Reg : TRegistry; // deklaruj zmienna dla klasy
begin
  Reg := TRegistry.Create;  // stworz zmienna
  try
    Reg.OpenKey('SoftwareRegApp', True); // utworz katalog
  finally
    Reg.Free; // zwolnij klase
  end;
end;


Taki oto kod spowoduje utworzenie katalogu (klucza) o nazwie RegApp w kluczu: HKEY_CURRENT_USERSoftware. Jak to wszystko się odbywa? Początek do zadeklarowanie zmiennej dla klasy, później następuje utworzenie klasy - to najważniejsze, bez tego program spowoduje błąd Access Violation. Zauważ, że wszystko jest zamknięte w wyjątkach (słowach try..finally ). Ty także tak rób, gdyż ew. błąd i tak spowoduje zwolnienie pamięci przydzielonej dla klasy TRegistry. Procedure OpenKey klasy TRegistry nie tylko otwiera klucz (jak można by się było domyśleć pod nazwie) ale także go tworzy w wypadku, gdy takowy nie istnieje. Decyduje o tym drugi parametr - jeżeli jest to True to taki klucz zostanie utworzony, gdy nie istnieje - jeżeli False - nie zostanie utworzony. Pierwszy parametr, to oczywiście ścieżka, gdzie klucz ostanie otworzony. Możesz to sprawdzić wpisując powyższy kod do swojej aplikacji. Następnie gdy wejdziesz do rejestru w kouczu HKEY_CURRENT_USER/Software zobaczysz katalog RegApp. Bardzo łatwo możesz także tworzyć pod katalogi - po prostu piszesz: Reg.OpenKey('SoftwareRegAppOpcje', True) i już zostanie stworzony pod katalog "Opcje".

Piszemy przykładowy program


W naszym programie wykorzystywać będziemy komponent TMonthCalendar, TEdit oraz TButton. W programie użytkownik będzie mógł wpisać swoje imię oraz datę urodzin. Potem program to "zapamięta" i w przypadku, gdy podana data urodzin równa się dacie dzisiejszej wyświetli okno z życzeniami :)

W tym celu należy do rejestru zapisać dwie wartości - datę (typu TDate ) oraz imię (typ: String ). Nie będzie to zbyt trudne. Cała procedura wygląda tak:

procedure TMainForm.btnAcceptClick(Sender: TObject);
var
  Reg : TRegistry; // deklaruj zmienna dla klasy
begin
  Reg := TRegistry.Create;  // stworz zmienna
  try
    Reg.OpenKey('SoftwareRegApp', True); // utworz katalog
 
    Reg.WriteString('Imie', edtName.Text); // zapisz imie
    Reg.WriteDate('Data', Calendar.Date); // zapisz date
  finally
    Reg.Free; // zwolnij klase
  end;
end;

Do zapisywania wartości tekstowych (typu String) służy procedura WriteString. Do zapisywania wartości typu TDate procedura WriteDate. Pierwszym parametrem jest nazwa nowej wartości, która widniała będzie w rejestrze, a druga wartość to właśnie wartość :) danej pozycji. Taki kod spowoduje zapisanie do rejestru kilku ważnych dla programu danych. Nie jest to trudne, prawda? Wszystko leży w kwestii zapamiętaniu kilku poleceń. Odczyt danych z rejestru również nie jest trudny - polecenia praktycznie są takie same, tyle, że zamiast Write pisze się Read.

Wygeneruj procedurę OnCreate formy i wpisz taki kod:

procedure TMainForm.FormCreate(Sender: TObject);
var
  Reg : TRegistry;
  KeyExists : Boolean;
begin
  Reg := TRegistry.Create;
  try
    KeyExists := Reg.OpenKey('SoftwareRegApp', False); // otworz klucz
    if not KeyExists then
    begin
      Calendar.Date := Now; // ustaw dzisijsza date na kalendarzu
      Exit; // nie rob juz nic...
    end;
 
    edtName.Text := Reg.ReadString('Imie'); // odczytaj imie i przypisz do kontrolki
    Calendar.Date := Reg.ReadDate('Data'); // odczytaj date i wyswietl w kalendarzu
  finally
    Reg.Free;
  end;
end;

Ta procedura jest tylko nieco bardziej skomplikowana, z tego powodu, że sprawdzamy, czy klucz istnieje. Dlaczego? Powód jest prosty. W przypadku, gdy program jest uruchamiany po raz pierwszy, klucz taki nie istnieje, a po próbie odczytu danych wystąpi wyjątek. Funkcja OpenKey zwraca True jeśli klucz istnieje, a False jeżeli nie istnieje. Dzięki temu właśnie możemy sprawdzić, czy program jest uruchamiany po raz pierwszy. Jeżeli więc klucz nie istnieje to do kalendarza przypisana jest data dzisiejsza, a dalsze czynności odczytu nie są już odczytywane. W przeciwnym wypadku dzięki funkcji ReadString oraz ReadDate dane są odczytywane i przypisane do komponentu. Parametr tych funkcji jest jeden - nazwa klucza.

Teraz pozostaje posprzątanie po sobie. Każdy program, który dopisuje coś do rejestru powinien mieć funkcje odinstalowania, w tym także usunięcia niepotrzebnych danych zawartych w rejestrze, gdy nie jest już konieczne ich używanie. Usuwanie klucza jest bardzo proste bo realizuje się za pomocą funkcji DeleteKey.  
procedure TMainForm.btnEraseClick(Sender: TObject);
var
  Reg : TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.DeleteKey('SoftwareRegApp');  // wykaowanie klucza
    Application.MessageBox('Klucze zostały prawidłowo usunięte.', 'Sukces', 
MB_OK + MB_ICONINFORMATION);
  finally
    Reg.Free;
  end;
end;

Jak widzisz w nawiasach podana jest ścieżka klucza do usunięcia. Jeżeli chcesz usunąć pojedynczą wartość w kluczu stosujesz DeleteValue.

Teraz już masz podstawowe informacje dotyczące dodawania kluczy do rejestrów. Oto kod źródłowy przykładowego programu:
(****************************************************************)
(*                                                              *)
(*                     Sample RegApp                            *)
(*           Copyright (c) 2001 by Adam Boduch                  *)
(*                  www.4programmers.net                        *)
(*                   [email protected]                          *)
(*                                                              *)
(****************************************************************)
 
unit MainFrm;
 
interface
 
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls;
 
type
  TMainForm = class(TForm)
    Calendar: TMonthCalendar;
    Label1: TLabel;
    edtName: TEdit;
    btnAccept: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnAcceptClick(Sender: TObject);
  end;
 
var
  MainForm: TMainForm;
 
implementation
 
{$R *.DFM}
 
uses Registry;
 
procedure TMainForm.FormCreate(Sender: TObject);
var
  Reg : TRegistry;
  KeyExists : Boolean;
begin
  Reg := TRegistry.Create;
  try
    KeyExists := Reg.OpenKey('SoftwareRegApp', False); // otworz klucz
    if not KeyExists then
    begin
      Calendar.Date := Now; // ustaw dzisijsza date na kalendarzu
      Exit; // nie rob juz nic...
    end;
 
    edtName.Text := Reg.ReadString('Imie'); // odczytaj imie i przypisz do kontrolki
    Calendar.Date := Reg.ReadDate('Data'); // odczytaj date i wyswietl w kalendarzu
  finally
    Reg.Free;
  end;
end;
 
procedure TMainForm.btnAcceptClick(Sender: TObject);
var
  Reg : TRegistry; // deklaruj zmienna dla klasy
begin
  Reg := TRegistry.Create;  // stworz zmienna
  try
    Reg.OpenKey('SoftwareRegApp', True); // utworz katalog
 
    Reg.WriteString('Imie', edtName.Text); // zapisz imie
    Reg.WriteDate('Data', Calendar.Date); // zapisz date
  finally
    Reg.Free; // zwolnij klase
  end;
end;
procedure TMainForm.btnEraseClick(Sender: TObject);
var
  Reg : TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.DeleteKey('SoftwareRegApp');  // wykaowanie klucza
    Application.MessageBox('Klucze zostały prawidłowo usunięte.', 'Sukces', 
MB_OK + MB_ICONINFORMATION);
  finally
    Reg.Free;
  end;
end;
 
end.

Zwróć uwagę, że otwierając klucz nie musisz podawać klucza głównego, np: HKEY_CURRENT_USER. Program domyślnie dopisuje tam dane. Ty jednak możesz to zmienić jeśli chcesz zapisać swoje dane gdzieś indziej. Klasa TRegistry posiada właściwość RootKey, do której przypisujesz nazw klucza głównego. Oto przykład:

Reg.RootKey := HKEY_CLASSES_ROOT;

Oczywiście przy pomocy klasy TRegistry możesz także zapisywać/odczytywać inne typy zmiennych. Ich nazwy można się łatwo domyśleć. Na przykład, że polecenie zapisujące liczbę Integer to WriteInteger, a odczytujące to ReadInteger.  

Oto inne przykłady:
// typ Integer
Reg.WriteInteger('WartoscInteger', 12); 
// zapisana liczba 12
 
// odczyt typu Integer
Edit1.Text := IntToStr(
Reg.ReadString('WartoscInteger')); 
 
// typ Boolean
Reg.WriteBool('WartoscBoolean', True); 
// zapisana wartość True
 
// odczytanie wartości Boolean:
Checkbox1.Checked := Reg.ReadBool(
'WartoscBoolean'); 
 
// typ zmienno - przecinkowy
Reg.WriteCurrency('WartoscCurrency', 3.12); 
// zapisanie 3.12
 
// odczyt wartości Currency:
Edit2.Text := CurrToStr(
Reg.ReadCurrency('WartoscCurrency')); 
 
// zapisz aktualną datę i czas
Reg.WriteDateTime('DataIczas', Now); 
// zapisz aktualną datę i czas
 
// odczytaj datę i czas
Edit3.Text := DateTimeToStr(
Reg.ReadDateTime('DataIczas')); // odczytaj datę i czas

14 komentarzy

bordeux 2007-08-19 14:57

Aby dodac wartosc hex to

var r:tregistry;
tablica:array of char;
linia:string;
i, j:integer;
begin
linia := ':00,00,00,00,00,00,10,40';
 
SetLength(tablica, length(linia) div 3);
i:=0;
j:=2;
while j<=length(linia) do begin
tablica[i]:=chr(strtoint('$'+linia[j]+linia[j+1]));
j:=j+3;
inc(i);
end;
r:=tregistry.Create;
r.RootKey:=HKEY_CURRENT_USER;
r.OpenKey('Software\cos',true);
r.WriteBinaryData('cos',tablica[0],length(tablica));
r.CloseKey;
r.Free;
end;

armagedon 2007-04-04 15:47

w jaki sposób wykonać kopie całego rejestru lub zaznaczonego głównego klucza np. HKEY_LOCAL_MACHINE ?? :)

Adam Boduch 2006-03-02 18:07

Nalezaloby sie zastanowic nad usunieciem tego tekstu... na gorze tego dokumentu dodalem link do aktualnej, rozszerzonej i bardziej rozbudowanej wersji.

ALT F4 2005-11-15 17:53

mnie takzę się przyda iż teraz wiekszośc programów (wiekszych) :P korzysta własnie z zapisywania do rejestru :P...:D

Stiopa 2005-04-21 18:56

Ok rozwiązałem problem rejestru typu REG_MULTI_SZ.
Pod tym adresem www.stiopaxxl.webpark.pl/EthernetProfile.zip jest program gdzie stosuje procedury do odczytu i zapisu tego brzydkiego typu.
Pozdrawiam.

Stiopa 2005-04-20 19:15

 ubaff REG_MULTI_SZ to tablica łańcuchów znaków ale jak to dziadostwo odczytać to nie wiem :-)

ubaff 2005-03-23 14:01

writeString pozwala zapisac rejest typu      \"REG_SZ\"
a jak zapisac typ      \"REG_MULTI_SZ\" ??

wotek 2005-03-17 20:13

"Rejestry" są w procesorach, a nie w W$ :-D

Anonymous AdSoft 2005-01-26 12:40

jak sprawdzić czy istniejeją jakieś dane w wartości jak istanieją to zrob coś else tez cos zrób...

chodzi mi o coś takiego:
Reg:=Tregistry.Create;
Reg.RootKey:=HKEY_CLASSES_ROOT;
Reg.OpenKey('CLSID\{D27CDB6E-AE6D-11cf-96B8-444553540000}\MiscStatus\1', true);
if Reg.ValueExists(, '131473') then
 CheckBox12.Checked:=false
 else
 CheckBox12.Checked:=true;

bardzo proszę o pomoc na maila: adsoft(at)gazeta(dot)pl
1. Ma sprawdzić wartość
(to akurat jest wartośc domyślna)
2. Ma sprawdzić dane w Wartości Domyślnej - czyli jeśli to: '131473' istnieje to zrob to else tamto...

krknet 2004-05-27 23:17

Hmm OK ale jak wstawić Klucz DWORD ???

czarownik 2003-07-19 02:01

brakuje jeszcze tylko Reg.WriteBinaryData a tego wlasnie mi trzeba... :(

RobinMaster 2003-06-24 23:56

Boski artykuł na pewno się przyda :D:D:D

Saddam Huzajn 2003-05-01 12:35

regedit a nie regEdit i nie registry.

mocarnik 2003-04-18 21:15

chyba pisze się regEdit a nie registry :-)