15.11.2013, Vladimír Klaus, navštíveno 6529x

Delphi
Systém
Windows

Nedávno mě jeden známý požádal o naprogramování malé aplikace, pomocí které by mohl provádět některé „vypínací akce“ s počítačem. V tomto článku si ukážeme funkce a postupy, které jsem použil. Výsledná aplikace AUDREY Restart PC je ke stažení na této stránce a je samozřejmě zcela zdarma.

Jak pomocí Delphi aplikace restartovat, vypnout nebo uspat počítač

Vypnutí, restart, odhlášení

Samotný princip není složitý – vlastně se jen volá systémová funkce s parametrem, který to zařídí. Například vypnutí počítače.

ExitWindowsEx(EWX_SHUTDOWN, 0);

Jenomže se může stát, že nám to bude nějaká aplikace blokovat, Windows se nás budou ptát, zda ji chceme ukončit, aplikace neodpovídá apod. Pokud toto nechceme řešit, příkaz se vylepší o konstantu, která vypnutí (nebo jiný příkaz) vynutí.

ExitWindowsEx(EWX_SHUTDOWN + EWX_FORCE, 0);

Tyto konstanty jsou definovány ve Winapi.Windows.pas. Tam najdete i ty další potřebné, které zajistí třeba odhlášení nebo restart.

ExitWindowsEx(EWX_LOGOFF + EWX_FORCE, 0);
ExitWindowsEx(EWX_REBOOT + EWX_FORCE, 0);

Situace se trochu komplikuje ve chvíli, kdy zjistíte, že vám toto z nějakého důvodu nefunguje. Možná je to tím, že nemáte práva nebo že váš systém (BIOS, grafická karta) danou akci nepodporuje. Pak budete muset doplnit do programu nějaké to testování…

Já už řadu let používám tuto složitější funkci, které předávám jen jeden parametr. Vynucení se přidává automaticky. Funguje spolehlivě i na 64bit Windows a byla použita při přípravě ukázkové aplikace.

procedure UkoncitWindows(aAkce: Shortint);
var
  hToken, hProcess: THandle;
  tp, prev_tp: TTokenPrivileges;
  Len : DWORD;

begin
  if Win32Platform = VER_PLATFORM_WIN32_NT then begin
    hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, GetCurrentProcessID);
    try
      if not OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,hToken) then Exit;
    finally
      CloseHandle(hProcess);
    end;

    try
      if not LookupPrivilegeValue('', 'SeShutdownPrivilege',tp.Privileges[0].Luid) then Exit;
      tp.PrivilegeCount := 1;
      tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
      if not AdjustTokenPrivileges(hToken, False, tp, SizeOf(prev_tp),prev_tp, Len) then Exit;
    finally
      CloseHandle(hToken);
    end;
  end;
  ExitWindowsEx(EWX_FORCE or aAkce, 0);
end;

Uspání a hibernace

Na tyto akce se musí úplně jinak. Nejprve si nadefinujeme odkaz na externí systémovou funkci SetSuspendState.

function SetSuspendState(hibernate, forcecritical, disablewakeevent: boolean): boolean;
   stdcall; external 'powrprof.dll' name 'SetSuspendState';

A pak ji použijeme. První volání počítač uspí, druhé ho hibernuje. Vše důležité řeší vlastně jen ten první parametr.

SetSuspendState(false, false, false);
SetSuspendState(true, false, false);

Pokud vás teď napadá, jaký je rozdíl mezi uspáním a hibernací, tak se to má takto:

Režim spánku spočívá v tom, že se počítač zdánlivě vypne, ale on pouze velice sníží spotřebu. Všechna rozpracovaná práce je uložena do paměti. Pokud počítač probudíte (třeba myší nebo klávesnicí), uvede se během několika vteřin do stavu, v jakém byl těsně před uspáním. Vše tedy běží a vy můžete okamžitě pokračovat v práci.

Režim hibernace je podobný režimu spánku, ale s tím rozdílem, že se veškerá rozpracovaná práce (stav paměti) uloží na disk a počítač se skutečně vypne. Pokud ho pak tlačítkem pro zapínání nastartujete, probíhá opravdový start počítače, ale na konci se uvede do stavu, v jakém jste ho hibernovali. Všechny spuštěné aplikace poběží (obnoví se jejich stav z disku) a vy i v tomto případě můžete pokračovat v práci.

Závěr

Pokud vás celá problematika více zajímá, doporučuji níže uvedené stránky. Bohužel je na webu i řada jiných podobných informací, které mohou být zkreslené nebo dokonce nepravdivé (i když třeba jen proto, že to fungovalo před 10 lety na starších Windows, ale dnes už ne). Pokud budete programovat aplikaci využívající takovéto speciální funkce, dbejte na kvalitu informací. Uživatelé to ocení.

http://www.tek-tips.com/faqs.cfm?fid=6881

http://msdn.microsoft.com/en-us/library/windows/desktop/aa376868(v=vs.85).aspx

http://windows.microsoft.com/cs-CZ/Windows7/Sleep-and-hibernation-frequently-asked-questions

Pochopitelně budu rád za připomínky nebo další náměty. Buď k tomuto článku nebo ukázkové aplikaci, kterou budu (občas) zlepšovat.