Condividi tramite


Funzione del gestore del controllo del servizio

Ogni servizio dispone di un gestore di controllo, la funzione gestore, 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 del controllo. Per un esempio, vedere Scrittura di una funzione del gestore di controlli.

Un servizio chiama la funzioneRegisterServiceCtrlHandlero RegisterServiceCtrlHandlerEx per registrare la 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 solo se la gestione del codice di controllo determina 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 funzioneControlService. 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 interrompersi 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 controllo 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 controllo, 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 del 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 di 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. Il gestore di controllo del servizio attende fino all'arresto del servizio o alla scadenza del valore di timeout preshutdown specificato(questo valore può essere impostato con la funzione ChangeServiceConfig2). Questo codice di controllo deve essere usato solo in circostanze particolari, perché un servizio che gestisce questo tipo di notifica blocca l'arresto del sistema fino all'arresto del servizio o alla scadenza dell'intervallo di timeout preshutdown.

Al termine delle notifiche preliminari, 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 rimane 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 il completamento dell'arresto del servizio. 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 nella WaitToKillServiceTimeout valore (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 a mano, 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 essere 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 per attendere 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 controllo servizi 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 multistringa contenente i nomi dei servizi nell'ordine in cui devono essere arrestati e assegnarli 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 funzionesetProcessShutdownParameters. SCM usa questa funzione per assegnare al gestore 0x1E0 priorità. Gestione controllo servizi invia notifiche SERVICE_CONTROL_SHUTDOWN quando viene chiamato il relativo 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