Funzione ServiceMain

Quando un programma di controllo del servizio richiede l'esecuzione di un nuovo servizio, Service Control Manager (SCM) avvia il servizio e invia una richiesta di avvio al dispatcher del controllo. Il dispatcher di controllo crea un nuovo thread per eseguire la funzione ServiceMain per il servizio. Per un esempio, vedere Scrittura di una funzione ServiceMain.

La funzione ServiceMain deve eseguire le attività seguenti:

  1. Inizializzare tutte le variabili globali.

  2. Chiamare la funzione RegisterServiceCtrlHandler immediatamente per registrare una funzione gestore per gestire le richieste di controllo per il servizio. Il valore restituito di RegisterServiceCtrlHandler è un handle di stato del servizio che verrà usato nelle chiamate per notificare lo stato del servizio.

  3. Eseguire l'inizializzazione. Se si prevede che il tempo di esecuzione del codice di inizializzazione sia molto breve (minore di un secondo), l'inizializzazione può essere eseguita direttamente in ServiceMain.

    Se si prevede che il tempo di inizializzazione sia maggiore di un secondo, il servizio deve usare una delle tecniche di inizializzazione seguenti:

    • Chiamare la funzione SetServiceStatus per segnalare SERVICE_RUNNING ma non accettare alcun controllo fino al termine dell'inizializzazione. Il servizio esegue questa operazione chiamando SetServiceStatus con dwCurrentState impostato su SERVICE_RUNNING e dwControlsAccepted impostato su 0 nella struttura SERVICE_STATUS . Ciò garantisce che SCM non invierà richieste di controllo al servizio prima di essere pronto e libera il SCM per gestire altri servizi. Questo approccio all'inizializzazione è consigliato per le prestazioni, soprattutto per i servizi di avvio automatico.

    • Report SERVICE_START_PENDING, accettare nessun controllo e specificare un hint di attesa. Se il codice di inizializzazione del servizio esegue attività che devono richiedere più tempo del valore dell'hint di attesa iniziale, il codice deve chiamare periodicamente la funzione SetServiceStatus (possibilmente con un hint di attesa modificato) per indicare che lo stato viene eseguito. Assicurarsi di chiamare SetServiceStatus solo se l'inizializzazione sta effettuando lo stato di avanzamento. In caso contrario, SCM può attendere che il servizio immetti lo stato SERVICE_RUNNING presupponendo che il servizio stia effettuando lo stato di avanzamento e impedisca l'avvio di altri servizi. Non chiamare SetServiceStatus da un thread separato, a meno che non si sia certi che il thread che esegue l'inizializzazione sia effettivamente in corso.

      Un servizio che usa questo approccio può anche specificare un valore check-point e aumentare periodicamente il valore durante un'inizializzazione lunga. Il programma che ha avviato il servizio può chiamare QueryServiceStatus o QueryServiceStatusEx per ottenere il valore di check point più recente da SCM e usare il valore per segnalare lo stato incrementale dell'utente.

  4. Al termine dell'inizializzazione, chiamare SetServiceStatus per impostare lo stato del servizio su SERVICE_RUNNING e specificare i controlli che il servizio è pronto per accettare. Per un elenco di controlli, vedere la struttura SERVICE_STATUS .

  5. Eseguire le attività del servizio o, se non sono presenti attività in sospeso, restituire il controllo al chiamante. Qualsiasi modifica nello stato del servizio garantisce una chiamata a SetServiceStatus per segnalare nuove informazioni sullo stato.

  6. Se si verifica un errore durante l'inizializzazione o l'esecuzione del servizio, il servizio deve chiamare SetServiceStatus per impostare lo stato del servizio su SERVICE_STOP_PENDING se la pulizia sarà lunga. Al termine della pulizia, chiamare SetServiceStatus per impostare lo stato del servizio su SERVICE_STOPPED dall'ultimo thread da terminare. Assicurarsi di impostare i membri dwServiceSpecificExitCode e dwWin32ExitCode della struttura SERVICE_STATUS per identificare l'errore.

Scrittura di una funzione ServiceMain