Umíme to s Delphi: 69. díl – práce se systémovým registrem

První díl seriálu v roce 2003 se bude zabývat dalším progresivním tématem: prací se systémovým registrem, přesněji řečeno způsobem, jakým jej využít k uchovávání nejrůznějších údajů našich aplikací. Uvidíte, že onen nabubřelý a nenáviděný moloch, jak o registru někdy smýšlíme, může být velmi užitečný – a jednoduše použitelný.
Než se do registru pustíme, splníme ovšem několik „restů“ z minulého dílu, v němž jsme se zabývali inicializačními soubory. Skončili jsme popisem metod, které jsou použitelné pro objekty tříd TIniFile i TMemIniFile a slíbili jsme si, že jednak vysvětlíme, k čemu je u TIniFile dobrá metoda UpdateFile a jednak popíšeme několik málo metod, které obsahuje pouze TMemIniFile a u TIniFile je nenalezneme.

Dodatek k třídám TIniFile a TMemIniFile

Nejprve si vysvětlíme zmíněnou metodu UpdateFile. Uvedli jsme si, že zavoláním této metody pro objekt TMemIniFile způsobíme zápis údajů z operační paměti (TMemIniFile pracuje s inicializačním souborem pouze „v paměti“) na disk (do fyzického souboru). Třída TIniFile ale pracuje přímo s diskem, má tedy UpdateFile pro tuto třídu nějaký význam?

Odpověď je ano i ne; u operačních systémů Windows 9x význam má, neboť tyto systémy mohou „interně“ bufferovat vstupně/výstupní operace, a tedy i přes použití třídy TIniFile je možné, že údaje budou zapsány pouze do paměti a ne fyzicky na disk. Zavoláním UpdateFile tak donutíme systém, aby všechny údaje uložené do vyrovnávací paměti skutečně a neodvratně „vyplivl“ na pevný disk do příslušného souboru *.ini (znalci asi používají pojem „flush“).

Rád bych zdůraznil, že toto „bufferování“ je něco úplně jiného než používání třídy TMemIniFile. Zatímco TMemIniFile pracuje celou dobu „vědomě“ s operační pamětí, třída TIniFile pracuje s diskovým souborem a je jen a jen věcí systému, že vstupně/výstupní operace vezme „do svých rukou“ a rozhodne používat při nich vyrovnávací paměť. Na principu to vůbec nic nemění.

V systémech Windows NT a Windows 2000 nejsou vstupně/výstupní operace nad soubory *.ini bufferovány vůbec, proto nebude mít volání UpdateFile žádný efekt. Mám-li být upřímný, nevím, jak je to v systému Windows XP, ale přikláním se k názoru, že bude situace stejná jako u Win NT/2000.

Další poznámka ke třídám TIniFile a TMemIniFile se bude týkat pouze druhé z nich. Ta totiž obsahuje několik málo metod, které TIniFile z pochopitelných důvodů nemá:

Metoda Popis
procedure Clear Vymaže všechna data ze souboru *.ini, který je aktuálně uložen ve vyrovnávací (operační) paměti.
procedure GetStrings(List: TStrings) Zkopíruje všechny data uložená v paměti v aktuálním souboru *.ini do seznamu List.
procedure Rename(const FileName: String; Reload: Boolean) Asociuje objekt třídy TMemIniFile s jiným souborem *.ini, než byl uveden při vytvoření tohoto objektu. Pomocí parametru Reload můžeme stanovit, zda se mají okamžitě načíst data z nového souboru. Pomocí této funkce tak můžeme snadno kopírovat data z jednoho souboru *.ini do jiného.
procedure SetStrings(List: TStrings) „Opačná“ metoda k GetStrings: data ze seznamu List přiřadí („uloží“) do aktuálního souboru *.ini v paměti.

Tolik k práci s inicializačními soubory. Věřím, že mi dáte za pravdu, že jejich použití je jistě elegantnější cestou k uchovávání dat aplikací, než implementace vlastního mechanismu a „ruční“ čtení/ukládání z/do textových nebo binárních souborů.

Úplně poslední poznámka k souborů *.ini: je nutné, abyste na ně pohlíželi jako na jakýkoliv jiný textový soubor. To, že je stanoven formát těchto souborů, vlastně nic neznamená a nijak nás to neomezuje. Inicializační soubory nejsou žádnou tajuplnou černou skříňkou, které bychom se měli bát. Pokud chceme či potřebujeme, můžeme s nimi pracovat „ručně“, bez použití tříd TIniFile a TMemIniFile. Můžeme klidně číst a zapisovat údaje jen prostřednictvím standardních funkcí souborové podpory. Otázkou samozřejmě je, proč bychom to dělali; touto poznámkou se jen pokouším zdůraznit, že popsaný mechanismus přístupu k těmto souborům je pouze jakási pomoc, kterou nám Delphi poskytuje, nicméně nejedná se o jediný možný přístup k využívání inicializačních souborů.

Práce se systémovým registrem

Jak bylo uvedeno v předchozím dílu, alternativním způsobem ukládání aplikačních dat je registr systému Windows. Je asi zbytečné dodávat, že pokud plánujeme přenos naší aplikace pod jiný operační systém (nabízí se třeba Linux), není možné registru použít. Jinak řečeno – pokud v aplikaci použijeme jakýkoliv mechanismus práce se systémovým registrem, stane se aplikace nepřenositelnou. Většinou nám to nevadí (vytváříme konkrétní aplikaci pro konkrétní účel a tedy pro konkrétní systém), ale pokud existují nějaké pochyby, je lepší se tomuto systémově závislému řešení vyhnout a použít soubory *.ini. Dalším řešením je využít jednu „specialitu“ Delphi – ale o tom až později.

Jak tedy využít registr operačního systému Windows? Než tuto otázku zodpovíme, vysvětlíme si jen velmi stručně, co to registr vlastně je a jak si jej můžeme prohlédnout.

Co je registr systému Windows

Dovolím si ocitovat z nápovědy systému Windows 2000:

Informace o konfiguraci systému Windows 2000 jsou uloženy v databázi, které se říká registr. Registr obsahuje profily všech uživatelů počítače a informace o systémovém hardwaru, nainstalovaných programech a nastavení vlastností. Systém Windows 2000 tyto informace při své činnosti neustále používá.

V nápovědě je dále uvedeno, že existují editory registru, které umožňují kontrolu a změnu registru, nicméně že taková úprava by neměla být nutná a nedoporučuje se upravovat nastavení registru ručně. Namísto toho Microsoft doporučuje umožnit změnu systémového registru programům systému Windows.

Přestože je to asi zbytečné, i já se připojím k varování: nesprávná úprava registru může vážně poškodit systém. Před prováděním změn v registru byste měli alespoň zálohovat veškerá cenná data v počítači.

Abych ale začátečníka příliš nepolekal: pokud by neopatrnou manipulací s registrem došlo k poškození systému, bude pravděpodobně možné registr opravit, případně obnovit ze zálohy.

Pokud se chceme podívat, co v registru je, je vhodné použít třeba program regedit, který je součástí systému Windows. Pro jeho spuštění stiskneme Start – Spustit a do příkazové řádky napíšeme regedit. Otevře se okno programu. Registr systému je organizován hierarchicky, jednotlivé hodnoty jsou skryty v klíčích a podklíčích. V levé části programu regedit vidíme stromovou hierarchii registru, v pravé pak údaje a jejich hodnoty pro jednotlivé klíče, resp. podklíče, viz následující obrázek:

Klepněte pro větší obrázek

Pokud se pomocí programu regedit trochu „porozhlédnete“ po systémovém registru, zjistíte, že skutečně skoro pro každý program, který na počítači máte instalován, existuje v registru záznam s celou řadou uchovávaných hodnot. Připravte se také na nepříjemné překvapení, které vás čeká v okamžiku, kdy zjistíte, že neméně hodnot se v registru nalézá i pro aplikace, které v systému již dávno nejsou (v extrémním případě nikdy nebyly). Důvodem tohoto nepořádku není ani tak registr jako takový, jako spíše „nekázeň“ (v některých případech však rozumné důvody) aplikací, které při své odinstalaci neodeberou údaje z registru, ale ponechají je na svém místě. Pokud tutéž aplikaci později znovu instalujeme, může si snadno „zjistit“, že už v systému jednou byla a zařídit se podle toho (např. nám oznámit, že zkušební doba vypršela apod.). Registr skutečně funguje jako velmi rozsáhlé skladiště všech důležitých dat – nejen systémových, ale také aplikačních.

A přesně toho my nyní využijeme. Proč bychom si do registru nemohli uvést také svá vlastní data, resp. data svých vlastních aplikací?

Práce s registrem v Delphi

Knihovna VCL obsahuje dvě třídy pro práci se systémovým registrem. Jak uvidíme, způsob jejich využívání je podobný práci s třídami TIniFile a TMemIniFile; vůbec obecně lze prohlásit, že filozofie práce s registrem se příliš neliší od práce s inicializačními soubory. Jedinou zásadní změnou je fyzické umístění informací (zatímco soubor *.ini si každý program „nese“ s sebou, případně nahrává do systémového adresáře, údaje v registru jsou centralizovaně uloženy na jediném místě).

Základní třídou pro práci s registrem je TRegistry. Tou se také budeme zabývat v další části článku. Druhou třídou je TRegistryIniFile, což je velmi zajímavá třída, která umožňuje pracovat s registrem a zároveň vytvářet přenositelné aplikace. Podrobnosti o této třídě si uvedeme později.

Třída TRegistry má vlastnosti a metody, jejichž názvy poměrně věrně korespondují se způsobem, jakým jsou v registru organizována data. Jinak řečeno – vlastnosti a metody TRegistry se jmenují jinak než vlastnosti a metody tříd pro práci se soubory *.ini. Pokud se podivujete, proč to vůbec zdůrazňuji, vyčkejte na popis třídy TRegistryIniFiles, u níž platí pravý opak. Pomocí třídy TRegistry můžeme velmi jednoduše otvírat, zavírat, ukládat, přesouvat, kopírovat a mazat jednotlivé klíče v registru (klíčem v terminologii systémového registru rozumíme totéž, co v souborech *.ini sekcí; v jednom klíči je obvykle uvedeno několik údajů a jejich hodnot).

Nejprve opět vytvoříme jednoduchou aplikaci, která bude používat k ukládání údajů systémového registru. Vytvoříme tutéž aplikaci jako v minulém dílu seriálu, ovšem namísto inicializačních souborů bude použit registr. Naše aplikace tedy po svém startu načte z registru jednak informace o poloze a velikosti okna a jednak obsah editačního pole. Tytéž údaje budou při ukončení aplikace opět uloženy do registru.

1. Vytvořte novou aplikaci, na hlavní formulář (Form1) umístěte jedno tlačítko (Button1) a jedno editační pole (Edit1). Tlačítko bude sloužit pouze k ukončení aplikace.

2. Nejprve je nutné přidat de sekce Uses jednotku Registry, neboť třída TRegistryje definována právě v této jednotce:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry;

3. Dále ošetříme událost OnClick tlačítka Button1:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form1.Close; { :-))) }
end;

4. Nyní ošetříme událost OnCreate hlavního formuláře:

procedure TForm1.FormCreate(Sender: TObject);
var Reg: TRegistry;
begin
  Form1.Caption:= `Ukazka TRegistry`;
  Button1.Caption := `&Konec`;

  Reg := TRegistry.Create(KEY_READ);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey(`\Software\Nase aplikace\Edit`, False) then begin
      Edit1.Text := Reg.ReadString(`Text`);
    end;

    if Reg.OpenKey(`\Software\Nase aplikace\Form`, False) then begin
      Form1.Top := Reg.ReadInteger(`Top`);
      Form1.Left := Reg.ReadInteger(`Left`);
      Form1.Height := Reg.ReadInteger(`Height`);
      Form1.Width := Reg.ReadInteger(`Width`);
      if Reg.ReadBool(`Maximized`) then
        Form1.WindowState := wsMaximized
      else
        Form1.WindowState := wsNormal;

    end;
    finally
    Reg.Free;
  end;
end;

Podrobnosti o jednotlivých metodách a jejich parametrech si opět uvedeme níže. Zde jen stručně několik důležitých poznatků:

  • parametrem konstruktoru TRegistry.Create je přístupové právo, s jakým bude objekt přistupovat do systémového registru. KEY_READ znamená přístup pro čtení, objekt tedy nemůže data v registru měnit;
  • pomocí metody RootKey stanovíme kořenový klíč registru, k němuž se budou vztahovat všechny další cesty. Obvykle se používá právě HKEY_LOCAL_MACHINE;
  • pomocí metody OpenKey otevřeme klíč, z něhož pak hodláme načítat jednotlivá data. V naší aplikaci používáme dva klíče: „Nase aplikace\Edit“ pro uchovávání obsahu editačního pole a „Nase aplikace\Form“ pro uchovávání informací o poloze, velikosti a stavu formuláře. Druhým parametrem OpenKey říkáme, zda objekt smí v případě, že požadovaný klíč neexistuje, klíč vytvořit. Protože zde pouze načítáme údaje, žádné vytváření klíčů nepožadujeme a volíme tedy False;
  • pro načítání jednotlivých hodnot z registru pak stejně jako u *.ini souborů používáme funkce ReadInteger, ReadString a ReadBool, přičemž jejich parametrem je vždy název načítané hodnoty. Název sekce (na rozdíl od *.ini) se samozřejmě neuvádí, neboť místo sekce pracujeme s klíčem otevřeným pomocí OpenKey.

5. Ošetříme událost OnClose hlavního formuláře. V ní naopak všechny potřebné údaje uložíme do registru:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var Reg: TRegistry;
begin
  Reg := TRegistry.Create(KEY_WRITE);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey(`\Software\Nase aplikace\Edit`, True) then begin
      Reg.WriteString(`Text`, Edit1.Text);
    end;

    if Reg.OpenKey(`\Software\Nase aplikace\Form`, True) then begin
      Reg.WriteInteger(`Top`, Form1.Top);
      Reg.WriteInteger(`Left`, Form1.Left);
      Reg.WriteInteger(`Height`, Form1.Height);
      Reg.WriteInteger(`Width`, Form1.Width);
      Reg.WriteBool(`Maximized`, Form1.WindowState = wsMaximized);
    end;

    finally
    Reg.Free;
  end;
end;

Opět si uvedeme jen minimum nejdůležitějších informací:

  • klíč otvíráme opět pomocí OpenKey, tentokráte však s (druhým) parametrem True, neboť pokud tento klíč neexistuje, chceme, aby byl vytvořen;
  • údaje pak zapisujeme pomocí funkcí WriteString, WriteInteger, WriteBool. Prvním parametrem je opět název údaje, druhým pak jeho hodnota;

6. Aplikace je hotova. Přeložte a opakovaně spusťte – uvidíte, že použití se nebude nijak lišit od předchozí verze uvedené před týdnem; jediným rozdílem je, že nikde nenalezneme žádný soubor „navíc“, vše je uvedeno v systémovém registru.

Klepněte pro větší obrázek

Na následujícím obrázku vidíte, co naše aplikace „provedla“ s registrem, jak vytvořila klíče „Nase aplikace\Edit“ a „Nase aplikace\Form“ a co uložila do druhého uvedeného:

Klepněte pro větší obrázek

Na závěr

Tolik pro dnešek k práci se systémovým registrem. Uvedli jsme si, co registr je, jak se používá a předvedli jsme si jednoduchý příklad, díky němuž zvládne ukládat informace do registru každý. Za týden začneme lehkým upozorněním a varováním na určitá specifika registru a řekneme si, k čemu bychom jej měli využívat a k čemu raději nikoliv. Potom se pod lupou podíváme na třídu TRegistry, u níž jsme dnes poznali jen zlomek jejích možností.

Diskuze (1) Další článek: Počítačové osudy - Michael Dell a jeho Dell Computer

Témata článku: Software, Windows, Programování, Filename, Zkušební doba, Nutná úprava, Systémový registr, Nepříjemná vlastnost, Popsaný mechanismus, Práce, Ruční úprava, Jednotlivý díl, Zavolání, Jediný způsob, Hlavní pole, Fyzické umístění, Editační funkce, Klíč, Jediný důvod, Jediná aplikace, Určitá specifika, Druhá sekce, Vyrovnávací paměť, Jednotlivý soubor, Registr

Určitě si přečtěte


Aktuální číslo časopisu Computer

Test 6 odolných telefonů a 22 powerbank

Srovnání technologií QLED a OLED

Měřte své sportovní výkony

Sady pro chytrou domácnost