Funzione Handler di controllo dei servizi

Ogni servizio ha un gestore di controllo, la funzione Handler , richiamata dal dispatcher di controllo quando il processo del servizio riceve una richiesta di controllo da un programma di controllo del servizio. Pertanto, questa funzione viene eseguita nel contesto del dispatcher di controllo. Per un esempio, vedere Scrittura di una funzione del gestore di controlli.

Un servizio chiama la funzione RegisterServiceCtrlHandler o RegisterServiceCtrlHandlerEx per registrare la relativa funzione del gestore di controllo del servizio.

Quando viene richiamato il gestore del controllo del servizio, il servizio deve chiamare la funzione SetServiceStatus per segnalarne lo stato a SCM solo se la gestione del codice di controllo causa la modifica dello stato del servizio. Se la gestione del codice di controllo non comporta la modifica dello stato del servizio, non è necessario chiamare SetServiceStatus.

Un programma di controllo del servizio può inviare richieste di controllo usando la funzione ControlService . Tutti i servizi devono accettare ed elaborare il codice di controllo SERVICE_CONTROL_INTERROGATE . È possibile abilitare o disabilitare l'accettazione degli altri codici di controllo chiamando SetServiceStatus. Per ricevere il codice di controllo SERVICE_CONTROL_DEVICEEVENT , è necessario chiamare la funzione RegisterDeviceNotification . I servizi possono anche gestire codici di controllo aggiuntivi definiti dall'utente.

Se un servizio accetta il codice di controllo SERVICE_CONTROL_STOP , deve essere arrestato alla ricezione, passando allo stato SERVICE_STOP_PENDING o SERVICE_STOPPED . Dopo che SCM invia questo codice di controllo, non invierà altri codici di controllo.

Windows XP: Se il servizio restituisce NO_ERROR e continua a essere eseguito, continua a ricevere i codici di controllo. Questo comportamento è cambiato a partire da Windows Server 2003 e Windows XP con Service Pack 2 (SP2).

Il gestore di controlli deve restituire entro 30 secondi oppure SCM restituisce un errore. Se un servizio deve eseguire un'elaborazione lunga quando il servizio esegue il gestore di controlli, deve creare un thread secondario per eseguire l'elaborazione lunga e quindi restituire dal gestore del controllo. Ciò impedisce al servizio di legare il dispatcher di controllo. Ad esempio, quando si gestisce la richiesta di arresto per un servizio che richiede molto tempo, creare un altro thread per gestire il processo di arresto. Il gestore del controllo deve semplicemente chiamare SetServiceStatus con il messaggio SERVICE_STOP_PENDING e restituire.

Quando l'utente arresta il sistema, tutti i gestori di controllo che hanno chiamato SetServiceStatus con il codice di controllo SERVICE_ACCEPT_PRESHUTDOWN ricevono il codice di controllo SERVICE_CONTROL_PRESHUTDOWN . La gestione controllo del servizio attende che il servizio si arresti o che scada il valore di timeout preshutdown specificato(questo valore può essere impostato con la funzione ChangeServiceConfig2 ). Questo codice di controllo deve essere usato solo in circostanze speciali, perché un servizio che gestisce questa notifica blocca l'arresto del sistema fino all'arresto del servizio o all'intervallo di timeout preshutdown scade.

Dopo aver completato le notifiche di preshutdown, tutti i gestori di controllo che hanno chiamato SetServiceStatus con il codice di controllo SERVICE_ACCEPT_SHUTDOWN ricevono il codice di controllo SERVICE_CONTROL_SHUTDOWN . Gli utenti ricevono una notifica nell'ordine in cui vengono visualizzati nel database dei servizi installati. Per impostazione predefinita, un servizio ha circa 20 secondi per eseguire attività di pulizia prima dell'arresto del sistema. Dopo questa scadenza, l'arresto del sistema procede indipendentemente dal fatto che l'arresto del servizio sia stato completato. Si noti che se il sistema viene lasciato nello stato di arresto (non riavviato o spento), il servizio continua a essere eseguito.

Se il servizio richiede più tempo per la pulizia, invia STOP_PENDING messaggi di stato, insieme a un hint di attesa, in modo che il controller del servizio sappia quanto tempo attendere prima di segnalare al sistema che l'arresto del servizio è stato completato. Tuttavia, per impedire a un servizio di arrestare l'arresto, esiste un limite alla durata di attesa del controller del servizio. Se il servizio viene arrestato tramite lo snap-in Servizi, il limite è di 125 secondi o di 125.000 millisecondi. Se il sistema operativo viene riavviato, il limite di tempo viene specificato nel valore WaitToKillServiceTimeout (in millisecondi) della chiave del Registro di sistema seguente:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

Importante

Un servizio non deve tentare di aumentare il limite di tempo modificando questo valore. Se è necessario impostare WaitToKillServiceTimeout manualmente, il valore deve essere espresso in millisecondi.

I clienti richiedono un arresto rapido del sistema operativo. Ad esempio, se un computer in esecuzione sull'alimentazione UPS non può completare l'arresto prima che l'ups esaurisca l'alimentazione, i dati possono andare persi. Pertanto, i servizi devono completare le attività di pulizia il più rapidamente possibile. È consigliabile ridurre al minimo i dati non salvati salvando regolarmente i dati, tenendo traccia dei dati salvati su disco e salvando solo i dati non salvati all'arresto. Poiché il computer è in fase di arresto, non dedicare tempo a rilasciare la memoria allocata o altre risorse di sistema. Se è necessario notificare a un server che si sta chiudendo, ridurre al minimo il tempo impiegato in attesa di una risposta, perché i problemi di rete potrebbero ritardare l'arresto del servizio.

Si noti che durante l'arresto del servizio, per impostazione predefinita, gestione configurazione sito non prende in considerazione le dipendenze. SCM enumera l'elenco dei servizi in esecuzione e invia il comando SERVICE_CONTROL_SHUTDOWN . Pertanto, un servizio potrebbe non riuscire perché un altro servizio da cui dipende è già stato arrestato.

Per impostare manualmente l'ordine di arresto dei servizi, creare un valore del Registro di sistema multistring contenente i nomi dei servizi nell'ordine in cui devono essere arrestati e assegnarlo al valore PreshutdownOrder della chiave di controllo, come indicato di seguito:

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

Per impostare l'ordine di arresto dei servizi dipendenti dall'applicazione, usare la funzione SetProcessShutdownParameters . SCM usa questa funzione per assegnare al gestore 0x1E0 priorità. SCM invia notifiche SERVICE_CONTROL_SHUTDOWN quando viene chiamato il gestore di controllo e attende che i servizi escino prima di tornare dal relativo gestore di controllo.

Scrittura di una funzione del gestore di controlli