Živě.cz o počítačích a internetu

Tipy a triky v Delphi, díl 92. - Vytvoření a zrušení bodu obnovy ve Windows XP

Jan Šindelář - 28.5.2003

Vytvoření a zrušení bodu obnovy ve Windows XP

O funkci bodu obnovy zřejmě nebude nutné se dlouze rozepisovat, ale pro ty z vás, kteří přesto tuto funkci neznají, snad jen drobné seznámení. Kdykoliv provádíte nějaký větší zásah do konfigurace operačního systému jako je třeba instalace nových ovladačů, vytvoří si systém tzv. bod obnovy. To je vlastně soubor, ve kterém je uložen stav systému před zásahem, který právě provádíte. V případě potíží pak pomocí nástroje Obnovení systému můžete vrátit provedenou změnu zpět právě pomocí uloženého bodu obnovy. Těchto uložených "stavů" můžete mít pochopitelně víc, takže se můžete vrátit poměrně daleko do historie. Navíc body obnovy nevytváří jen systém automaticky, ale jako uživatel máte možnost si jej kdykoliv vytvořit ručně. Myslím, že tato funkce je na rozdíl od některých jiných "vylepšení" Windows XP hodně užitečná (i když teď si nejsem zcela jist, jestli tato funkce nebyla již ve Windows ME) a kupodivu i funkční. Alespoň jsem zatím na žádný problém nenarazil.

Tolik tedy malé vysvětlení úvodem a nyní se již vrhněme na Delphi. Jistě mi dáte za pravdu, že některé aplikace občas udělají v systému takový nepořádek, že pak nevíte, co opravovat dřív. Nemusí to však být jen vinou špatného naprogramování. Existují aplikace, sloužící k různým úpravám systému, vylepšování ovladačů a podobně. Ty jsou potenciálně nebezpečné už ze své podstaty a rozumný autor vás na riziko vždy upozorní. Existují ale i další rozličné rizikové funkce, které aplikace mohou mít a v takovém případě je jistě dobré vytvořit (či nabídnout uživateli vytvoření) bod obnovy.

K celé operaci využijeme příslušnou funkci z knihovny SrClient.dll, nastavíme příslušný název bodu obnovy a je hotovo. Náš testovací příklad nejprve vytvoří bod obnovy a hned v zápětí jej zase odstraní.

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  BEGIN_SYSTEM_CHANGE = 100;
  END_SYSTEM_CHANGE  = 101;
  APPLICATION_INSTALL =  0;
  CANCELLED_OPERATION = 13;
  MAX_DESC = 64;
  MIN_EVENT = 100;

type
PRESTOREPTINFOA = ^_RESTOREPTINFOA;
_RESTOREPTINFOA = packed record
                    dwEventType: DWORD;
                    dwRestorePtType: DWORD;
                    llSequenceNumber: INT64;
                    szDescription: array [0..MAX_DESC] of CHAR;
                  end;

RESTOREPOINTINFO = _RESTOREPTINFOA;
PRESTOREPOINTINFOA = ^_RESTOREPTINFOA;

PSMGRSTATUS = ^_SMGRSTATUS;
_SMGRSTATUS = packed record
                nStatus: DWORD;
                llSequenceNumber: INT64;
              end;

STATEMGRSTATUS =  _SMGRSTATUS;
PSTATEMGRSTATUS =  ^_SMGRSTATUS;

function SRSetRestorePointA(pRestorePtSpec: PRESTOREPOINTINFOA; pSMgrStatus: PSTATEMGRSTATUS): Bool; stdcall; external `SrClient.dll` Name `SRSetRestorePointA`;

procedure TForm1.Button1Click(Sender: TObject);
var
  RestorePtSpec: RESTOREPOINTINFO;
  SMgrStatus: STATEMGRSTATUS;
begin
  RestorePtSpec.dwEventType := BEGIN_SYSTEM_CHANGE;
  RestorePtSpec.dwRestorePtType := APPLICATION_INSTALL;
  RestorePtSpec.llSequenceNumber := 0;
  RestorePtSpec.szDescription := `Název bodu obnovení`;
  if (SRSetRestorePointA(@RestorePtSpec, @SMgrStatus)) then
  begin
    ShowMessage(`Bod obnovy vytvoren.`);
    {---------------------------------------------}
    {---------------------------------------------}
    RestorePtSpec.dwEventType := END_SYSTEM_CHANGE;
    RestorePtSpec.dwRestorePtType  := CANCELLED_OPERATION;
    RestorePtSpec.llSequenceNumber := SMgrStatus.llSequenceNumber;
    if (SRSetRestorePointA(@RestorePtSpec, @SMgrStatus)) then ShowMessage(`Bod obnovy zrusen.`)
                                                          else ShowMessage(`Bod obnovy nelze zrusit.`);
    {---------------------------------------------}
    {---------------------------------------------}
  end
    else ShowMessage(`Bod obnovy nelze vytvorit.`);
  end;
end.

Kód, který je ohraničen z obou stran dvojitou čarou v poznámkách, slouží k odstranění právě vytvořeného bodu obnovy (na základě parametru llSequenceNumber). Praktické využití má tedy hlavně první část kódu, takže minimálně pro ověření funkčnosti, zda byl bod obnovy vůbec vytvořen, označte nejprve ohraničenou část kódu složenými závorkami jako komentář. Pak si můžete ověřit i funkce na odstranění. V ostré aplikaci bych ale nechal mazání nebo dokonce návrat stavu systému na základě nějakého dříve uloženého bodu obnovy raději na uživateli a příslušném nástroji k tomu určenému.

Ještě malá organizační poznámka na závěr, abych poněkud odlehčil mojí emailové schránce. Stále častěji se ptáte, zda není možné stáhnout si nějak celý seriál, aniž by bylo nutné procházet jednotlivé stránky a postupně si je ukládat. Tak tedy, pravidelní čtenáři si jistě vzpomenou, že první souhrnný balík (soubor ve formátu nápovědy Windows) s díly seriálu 1 až 55 již vyšel, výborným způsobem jej zpracoval pan Petr Brant a odkaz na stažení najdete na konci 60. dílu seriálu zde. Další podobný souhrn, pokud to jen čas dovolí, se pokusím v rozumné formě zajistit po vydání jubilejního stého dílu, takže již stačí jen chvilku počkat.