Servizi Win32 che interagiscono con i dispositivi

Un servizio Win32 ideale installato tramite INF AddService che interagisce con i dispositivi si comporta in modo simile al modo in cui un driver interagisce con i dispositivi. Un driver viene caricato e scaricato a seconda della presenza di un dispositivo e un servizio Win32 che interagisce con i dispositivi deve seguire questo stesso modello di avvio e arresto a seconda della presenza di un dispositivo.

I servizi devono iniziare solo quando un'interfaccia del dispositivo è presente e abilitata per interagire con e arrestare quando l'interfaccia del dispositivo non è più abilitata. Questo modello di progettazione garantisce un servizio affidabile che riduce al minimo il comportamento indesiderato e non definito. Verrà illustrato come deve essere progettato un servizio per seguire questo modello.

Installazione del servizio

Per installare il servizio, usare la direttiva INF AddService . In questo modo sarà possibile creare e avviare il servizio.

Aggiungere l'impostazione che rende l'avvio della richiesta del servizio. Questa operazione può essere eseguita impostando StartType=0x3 che rende avviato il trigger del servizio.

Il passaggio finale di questa sezione consiste nell'usare la direttiva AddTrigger per avviare il servizio quando arriva un'interfaccia del dispositivo (vedere AddService per altri dettagli su AddTrigger). Di seguito è riportato un esempio di come deve essere usato AddTrigger:

[UserSvc_Install]
ServiceType   = 0x10 ; SERVICE_WIN32_OWN_PROCESS
StartType     = 3    ; SERVICE_DEMAND_START
ErrorControl  = 0    ; SERVICE_ERROR_IGNORE
ServiceBinary = %13%\oemsvc.exe
AddTrigger    = UserSvc_AddTrigger

[UserSvc_AddTrigger]
TriggerType = 1                           ; SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL
Action      = 1                           ; SERVICE_TRIGGER_ACTION_SERVICE_START
SubType     = %GUID_DEVINTERFACE_OSRFX2%  ; Interface class GUID
DataItem    = 2, "USB\VID_0547&PID_1002"  ; SERVICE_TRIGGER_DATA_TYPE_STRING

Si noti che HardwareId specificato in DataItem è facoltativo e in genere necessario solo quando si usa un'interfaccia di classe generica per ambito del trigger in un dispositivo più specifico.

Runtime del servizio

Dal punto di vista del runtime, il primo passaggio per il servizio deve essere quello di registrare per le notifiche dell'interfaccia del dispositivo. Indicazioni prescrittive su come eseguire questa operazione sono disponibili in questa pagina: Registrazione per la notifica dell'arrivo dell'interfaccia dispositivo e rimozione del dispositivo.

In particolare, è consigliabile usare CM_Register_Notification con il flag di CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE per eseguire la registrazione appropriata delle notifiche dell'interfaccia del dispositivo.

Nota

Quando si avvia un servizio, non è possibile basarsi sul fatto che si riceveranno notifiche sull'interfaccia del dispositivo perché la notifica di arrivo potrebbe essere già passata, soprattutto se un arrivo dell'interfaccia del dispositivo è la causa dell'avvio del servizio. È invece necessario ottenere un elenco di interfacce del dispositivo per verificare se sono già presenti interfacce.

Dopo aver registrato le notifiche per le interfacce del dispositivo, si riceverà una notifica sulle nuove interfacce del dispositivo abilitate o esistenti. È possibile individuare il percorso dell'interfaccia del dispositivo dal callback di notifica. Per eseguire query sull'elenco delle interfacce dispositivo esistenti per esaminare le interfacce del dispositivo esistenti prima dell'avvio del servizio e della registrazione per le notifiche, è possibile ottenere un elenco di interfacce dispositivo tramite API, ad esempio CM_Get_Device_Interface_List.

Nota

È possibile che l'interfaccia del dispositivo arrivi tra la registrazione per le notifiche e il recupero di un elenco di interfacce dispositivo già presenti nel sistema. In tal caso, l'interfaccia del dispositivo verrà elencata sia nel callback della notifica che nell'elenco delle interfacce del dispositivo.

Se si vuole interagire con l'interfaccia del dispositivo con le API di I/O, dopo aver trovato l'interfaccia del dispositivo desiderata, aprire un handle all'interfaccia tramite CreateFile.

Il passaggio successivo consiste nel registrare le notifiche secondarie per ogni handle per ricevere una notifica delle modifiche dello stato al dispositivo, ad esempio i tentativi di eseguire query sulla rimozione del dispositivo o sul dispositivo. Questa operazione può essere eseguita usando CM_Register_Notification con il flag di CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE . Seguendo le indicazioni riportate nella registrazione per la notifica dell'arrivo dell'interfaccia del dispositivo e la rimozione del dispositivo , l'handle può essere rilasciato di conseguenza.

Gli arrivi e le rimozione dell'interfaccia del dispositivo devono essere monitorati in modo che la rimozione dell'ultima interfaccia del dispositivo che il servizio possa voler interagire con significa che il servizio può essere arrestato. Dopo aver rimosso l'ultima interfaccia, arrestare il servizio (sono disponibili informazioni dettagliate in questa pagina). Questa operazione può essere eseguita seguendo questa procedura:

  1. Pubblicare SERVICE_STOP_PENDING stato in SCM per indicare che il servizio sta andando verso il basso

  2. Inizializzare/pulire tutto ciò che il servizio usava

  3. Pubblicare SERVICE_STOP stato su SCM per completare l'operazione di arresto

Se il servizio viene arrestato, assicurarsi di controllare e passare tutti gli handle aperti esistenti alle interfacce del dispositivo (potrebbero non essere presenti) e pulirli.

L'interfaccia del dispositivo può tornare durante l'installazione del dispositivo, l'abilitazione/disabilitazione del dispositivo, l'enumerazione del dispositivo, il riavvio del sistema o durante altri scenari non elencati. Quando l'interfaccia del dispositivo torna, il servizio verrà avviato in base alla registrazione iniziale del trigger.

Questo flusso garantisce che il servizio inizi all'arrivo di un'interfaccia del dispositivo e si arresta quando l'ultima interfaccia del dispositivo non è più presente.

È disponibile un esempio in GitHub che illustra come un servizio può sfruttare questo flusso di eventi. L'esempio è disponibile qui: Esempio di servizio Win32.

È inoltre possibile trovare una documentazione utile relativa a AddTrigger nella pagina AddService .