Sdílet prostřednictvím


Funkce obslužné rutiny řízení služby

Každá služba má obslužnou rutinu řízení, obslužnou rutinu funkci, která je vyvolána dispečerem řízení, když proces služby obdrží žádost o řízení z programu řízení služby. Proto se tato funkce spustí v kontextu dispečera řízení. Příklad najdete v tématu Zápis funkce obslužné rutiny ovládacího prvku.

Služba volá RegisterServiceCtrlHandler nebo RegisterServiceCtrlHandlerEx funkce pro registraci funkce obslužné rutiny řízení služby.

Při vyvolání obslužné rutiny ovládacího prvku služby musí služba volat funkci SetServiceStatus, aby ohlásila stav SCM pouze v případě, že zpracování řídicího kódu způsobí změnu stavu služby. Pokud zpracování řídicího kódu nezpůsobí změnu stavu služby, není nutné volat SetServiceStatus.

Program řízení služeb může odesílat žádosti o řízení pomocí funkce ControlService. Všechny služby musí přijmout a zpracovat kód řízení SERVICE_CONTROL_INTERROGATE. Přijetí ostatních kódů ovládacích prvků můžete povolit nebo zakázat voláním SetServiceStatus. Chcete-li přijmout SERVICE_CONTROL_DEVICEEVENT řídicí kód, musíte volat RegisterDeviceNotification funkce. Služby můžou také zpracovávat další uživatelsky definované řídicí kódy.

Pokud služba přijme kontrolní kód SERVICE_CONTROL_STOP, musí se po přijetí zastavit, a to buď do SERVICE_STOP_PENDING, nebo do SERVICE_STOPPED stavu. Jakmile SCM odešle tento řídicí kód, neodešle jiné řídicí kódy.

Systému Windows XP: Pokud služba vrátí NO_ERROR a pokračuje ve spuštění, bude nadále přijímat řídicí kódy. Toto chování se změnilo od systémů Windows Server 2003 a Windows XP s aktualizací Service Pack 2 (SP2).

Obslužná rutina ovládacího prvku se musí vrátit do 30 sekund nebo SCM vrátí chybu. Pokud služba musí provádět zdlouhavé zpracování, když služba spouští obslužnou rutinu ovládacího prvku, měla by vytvořit sekundární vlákno pro provádění zdlouhavého zpracování a pak se vrátit z obslužné rutiny ovládacího prvku. Tím zabráníte službě v zavazování řídicího dispečera. Například při zpracování žádosti o zastavení pro službu, která trvá dlouhou dobu, vytvořte další vlákno pro zpracování procesu zastavení. Obslužná rutina ovládacího prvku by měla jednoduše zavolat SetServiceStatus se zprávou SERVICE_STOP_PENDING a vrátit se.

Když uživatel vypne systém, všechny obslužné rutiny ovládacích prvků, které volaly SetServiceStatus s kódem ovládacího prvku SERVICE_ACCEPT_PRESHUTDOWN obdrží kód ovládacího prvku SERVICE_CONTROL_PRESHUTDOWN. Správce řízení služeb počká, dokud se služba nezastaví nebo nevyprší zadaná hodnota časového limitu předshutu (tuto hodnotu je možné nastavit pomocí funkce ChangeServiceConfig2). Tento řídicí kód by se měl používat pouze za zvláštních okolností, protože služba, která zpracovává toto oznámení, blokuje vypnutí systému, dokud služba nezastaví nebo nevyprší časový limit před ukončením.

Po dokončení oznámení o předběžném ukončení obdrží všechny obslužné rutiny ovládacích prvků, které volaly SetServiceStatus, kód ovládacího prvku SERVICE_ACCEPT_SHUTDOWN obdrží kód ovládacího prvku SERVICE_CONTROL_SHUTDOWN. Jsou upozorněni v pořadí, v jakém se zobrazují v databázi nainstalovaných služeb. Ve výchozím nastavení má služba přibližně 20 sekund k provádění úloh čištění před vypnutím systému. Po uplynutí této doby bude vypnutí systému pokračovat bez ohledu na to, jestli je vypnutí služby dokončené. Všimněte si, že pokud systém zůstane ve stavu vypnutí (nerestartováno nebo vypnuto), služba bude dál spuštěna.

Pokud služba vyžaduje více času na vyčištění, odesílá STOP_PENDING stavové zprávy spolu s nápovědou k čekání, takže kontroler služby ví, jak dlouho má čekat, než se nahlásí systému, že je vypnutí služby dokončeno. Pokud ale chcete službě zabránit v zastavení vypnutí, existuje omezení, jak dlouho kontroler služby čeká. Pokud se služba vypíná prostřednictvím modulu snap-in Služby, limit je 125 sekund nebo 125 000 milisekund. Pokud se operační systém restartuje, je časový limit zadaný v WaitToKillServiceTimeout hodnotu (v milisekundách) následujícího klíče registru:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

Důležitý

Služba by se neměla pokoušet o zvýšení časového limitu úpravou této hodnoty. Pokud potřebujete nastavit WaitToKillServiceTimeout rukou, měla by být hodnota v milisekundách.

Zákazníci vyžadují rychlé vypnutí operačního systému. Pokud například počítač spuštěný na napájení UPS nemůže dokončit vypnutí před vyčerpáním napájení UPS, může dojít ke ztrátě dat. Služby by proto měly co nejrychleji dokončit úlohy čištění. Osvědčeným postupem je minimalizovat neuložené data tím, že data pravidelně ukládáte, sledujete data uložená na disk a ukládáte jenom neuložené data při vypnutí. Vzhledem k tomu, že se počítač vypíná, neutrácejte čas uvolněním přidělené paměti nebo jiných systémových prostředků. Pokud potřebujete oznámit serveru, že odcházejí, minimalizujte čas strávený čekáním na odpověď, protože problémy se sítí můžou zpozdit vypnutí služby.

Mějte na paměti, že během vypnutí služby ve výchozím nastavení SCM nebere v úvahu závislosti. SCM vytvoří výčet seznamu spuštěných služeb a odešle příkaz SERVICE_CONTROL_SHUTDOWN. Služba proto může selhat, protože jiná služba, na které závisí, je již zastavena.

Pokud chcete nastavit pořadí vypnutí služeb ručně, vytvořte hodnotu registru s víceřetězci, která obsahuje názvy služeb v pořadí, ve kterém by měly být vypnuty, a přiřaďte ji PreshutdownOrder hodnotu:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PreshutdownOrder="Shutdown Order"

Pokud chcete nastavit pořadí vypnutí závislých služeb z vaší aplikace, použijte funkci SetProcessShutdownParameters. SCM používá tuto funkci k udělení priority obslužné rutiny 0x1E0. SCM odesílá SERVICE_CONTROL_SHUTDOWN oznámení, když je volána jeho obslužná rutina řízení a čeká na ukončení služeb před návratem z obslužné rutiny ovládacího prvku.

zápisu funkce obslužné rutiny ovládacího prvku