Delphi - Windows NT alapú rendszerek időzített leállítása

forráskód letöltése
Ebben a cikkben egy olyan komponenst készítünk, amelynek segítségével leállíthatunk, vagy újraindíthatunk egy Windows NT alapú rendszert. A leállítást, illetve újraindítást másodperc pontossággal időzíthetjük. Amikor a leállítási folyamat elindul, tájékoztatjuk a felhasználót, és az időzítés segítségével lehetőséget biztosíthatunk számára munkájának befejezéséhez.
A mellékelt példaprogram megnyitása előtt az NTShutDown.pas-ban lévő komponenst telepítenie kell a Delphi alá. Ehhez válassza a Component - Install Component menüpontot.
A komponens felhasználása
A komponens használatának feltétele, hogy az éppen bejelentkezett felhasználó rendelkezzen leállítási joggal.
A komponenst helyezze el a Form-on. A ComputerName tulajdonságban adja meg a számítógép nevét (pl.: DSO1). A Time tulajdonság beállításával megadhatja, hogy a leállítási folyamat az aktiválástól kezdődően hány másodperc múlva történjen meg. A Reboot tulajdonság igazra vagy hamisra állításával adható meg, hogy újraindítás, vagy leállítás történjen. Ha a Reboot értéke igaz, akkor újraindítást kezdeményezünk.
Ha a fenti tulajdonságokat beállítottuk, akkor a Shutdown metódus meghívásával elindul a rendszer leállítása, melyet az AbortShutDown metódus meghívásával még megszakíthatunk. Mindkét metódus paraméterek nélküli.
Amikor a folyamat elindul, az operációs rendszer egy rendszerablakon keresztül tájékoztatja majd a felhasználót a leállítási folyamat elindulásáról és a végrehajtásig lévő maradék időről.
A komponens elkészítése
Komponensünket a TComponent osztályból származtatjuk. A futási időben láthatatlan komponensek csoportját fogja bővíteni.
Három tulajdonságra van szükségünk. A számítógépünk nevét a ComputerName, string típusú tulajdonságban adhatjuk meg. Az időzítéshez szükséges a Time, word típusú tulajdonság. A leállítás, vagy újraindítás eldöntésére egy logikai változót használunk, Reboot néven. Igaz érték esetén újraindításról lesz szó.
A ShutDown metódus
A rendszer leállítását a ShutDown metódus meghívásával indíthatjuk el.
procedure TNTShutDown.ShutDown;
var
  Count: Cardinal;
  Msg : String;
  Priv: TOKEN_PRIVILEGES;
  TokenHandle: Cardinal;
begin
  if OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,TokenHandle) then begin
    if LookupPrivilegeValue(Nil,'SeShutDownPrivilege',Priv.Privileges[0].Luid) then begin
      Priv.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
      Priv.PrivilegeCount:=1;
      AdjustTokenPrivileges(TokenHandle,False,Priv,0,Nil, Count);
      if GetLastError<>ERROR_SUCCESS then ShowMessage('Hiba történt a jogok beállítása közben!');
    end
    else ShowMessage('Hiba - Nincs rendszerleállítás joga!');
  end
  else ShowMessage('Hiba - A hozzáférési jogokat nem lehet lekérdezni!');
  Msg:='A rendszer leállítása '+IntToStr(FTime)+' másodperc múlva!';
InitiateSystemShutDown(PChar(FComputerName),PChar(Msg),FTime,True,FReboot);
end;
A TOKEN_PRIVILEGES egy struktúra. Ez a struktúra írja le az egyes folyamatokhoz rendelt hozzáférési jogokat. A Priv változó egy ilyen struktúra tárolására szolgál.
Egy NT rendszerben csak az állíthatja le a rendszert, akinek van rendszerleállítási joga. Ez igaz a folyamatokra is. A jogokat úgynevezett tokenek tárolják. A forráskódban API hívások sokaságát látjuk, most nézzük meg a kódot részletesebben.
OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,TokenHandle)
Az OpenProcessToken függvény megnyitja a hozzáférési adatokat tároló tokent. A TOKEN_ADJUST_PRIVILEGES jog szükséges a jogok megváltoztatásához, a TOKEN_QUERY, pedig a jogok lekérdezéséhez. A függvény az aktuális folyamat jogait kérdezi le. A TokenHandle fogja azonosítani a tokent.
LookupPrivilegeValue(Nil,'SeShutDownPrivilege',Priv.Privileges[0].Luid)
A LookupPrivilegeValue lekérdezi a „SetShutDownPrivilege” jog azonosítóját, melyet a Priv változóban eltárol. A Priv változó adatait módosítjuk.
Priv.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
Priv.PrivilegeCount:=1;
A Priv változó értékeinek módosításával aktiváljuk a leállítási jogot, az AdjustTokenPrivileges függvény segítségével.
AdjustTokenPrivileges(TokenHandle,False,Priv,0,Nil, Count);
Az Msg változóba azt az üzenetet tároljuk el, aminek a leállítás rendszerablakban meg kell jelennie.
Msg:='A rendszer leállítása '+IntToStr(FTime)+' másodperc múlva!';
És végül kezdeményezhetjük a rendszer leállítását, az InitiateSystemShutdown paranccsal.
InitiateSystemShutDown(PChar(FComputerName),PChar(Msg),FTime,True,FReboot);
Az AbortShutDown metódus
procedure TNTShutDown.AbortShutDown;
begin
  AbortSystemShutDown(PChar('\\'+FComputerName));
end;
Az AbortSystemShutdown API függvény meghívásával tudjuk a leállítási folyamatot megszakítani. Csak akkor van értelme meghívni ezt a metódust, ha már elkezdődött a leállítási folyamat.