Compartir a través de


Servicios Win32 que interactúan con dispositivos

Un servicio Win32 ideal instalado a través de INF AddService que interactúa con dispositivos se comporta de forma similar a cómo interactúa un controlador con los dispositivos. Un controlador se carga y descarga en función de la presencia de un dispositivo y un servicio Win32 que interactúe con los dispositivos debe seguir este mismo patrón de inicio y detención en función de la presencia de un dispositivo.

Los servicios solo deben iniciarse cuando hay una interfaz de dispositivo presente y habilitada para interactuar con y detener cuando la interfaz del dispositivo ya no está habilitada. Este patrón de diseño garantiza un servicio sólido que minimiza el comportamiento no deseado y indefinido. Le guiaremos por cómo se debe diseñar un servicio para seguir este patrón.

Instalación del servicio

Para instalar el servicio, use la directiva INF AddService . Esto le permitirá crear e iniciar el servicio.

Agregue la configuración para que el servicio inicie bajo demanda. Esto se puede lograr estableciendo StartType=0x3 que hace que se inicie el desencadenador de servicio.

El último paso de esta sección es usar la directiva AddTrigger para que el servicio se inicie cuando llegue una interfaz de dispositivo (consulte AddService para obtener más información sobre AddTrigger). A continuación se muestra un ejemplo de cómo se debe usar 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

Tenga en cuenta que el HardwareId especificado en DataItem es opcional y, por lo general, solo es necesario cuando se usa una interfaz de clase genérica para limitar el ámbito del desencadenador a un dispositivo más específico.

Tiempo de ejecución del servicio

Desde la perspectiva de tiempo de ejecución, el primer paso para su servicio debe ser registrarse para recibir notificaciones de la interfaz de dispositivo. Puede encontrar instrucciones prescriptivas sobre cómo hacerlo en esta página: Registro para la notificación de la llegada de la interfaz de dispositivo y eliminación de dispositivos.

En concreto, debe usar CM_Register_Notification con el indicador CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE para realizar el registro adecuado de las notificaciones de la interfaz de dispositivo.

Nota:

Cuando se inicia un servicio, no se puede confiar en que se recibirán notificaciones de interfaz de dispositivo, ya que es posible que la notificación de llegada ya haya pasado, especialmente si es la llegada de una interfaz de dispositivo la causa del inicio del servicio. En su lugar, debe obtener una lista de interfaces de dispositivo para comprobar si ya hay interfaces presentes.

Una vez que se haya registrado para recibir notificaciones para interfaces de dispositivo, recibirá una notificación sobre las nuevas interfaces de dispositivo habilitadas o las interfaces de dispositivo existentes que se están deshabilitando. Puede descubrir la ruta de acceso de la interfaz del dispositivo desde la devolución de llamada de notificación. Para consultar la lista de interfaces de dispositivo existentes para examinar las interfaces de dispositivo que existían antes de que el servicio se iniciara y registrara para las notificaciones, puede obtener una lista de interfaces de dispositivo a través de API como CM_Get_Device_Interface_List.

Nota:

Existe la posibilidad de que la interfaz del dispositivo llegue entre el registro de notificaciones y la recuperación de una lista de las interfaces de dispositivo ya presentes en el sistema. En ese caso, la interfaz del dispositivo se mostrará en el callback de notificación y en la lista de interfaces de dispositivos.

Si quiere interactuar con la interfaz de dispositivo con las API de E/S, una vez que haya encontrado la interfaz de dispositivo deseada, abra un identificador para la interfaz a través de CreateFile.

El siguiente paso es registrarse para recibir notificaciones secundarias por controlador para recibir notificaciones de cambios de estado en el dispositivo, como intentos de consultar la eliminación del dispositivo o el dispositivo que se va. Esto se puede hacer mediante CM_Register_Notification con la bandera CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE. Siguiendo las instrucciones de Registro para la notificación de la llegada de la interfaz de dispositivo y la eliminación de dispositivos, se asegurará de que cuando un dispositivo sea desconectado, el identificador pueda ser liberado en consecuencia.

Se debe realizar un seguimiento de las llegadas y eliminaciones de las interfaces de dispositivo para que, cuando se elimine la última interfaz con la que el servicio pueda interactuar, el servicio pueda ser detenido. Una vez que se haya quitado la última interfaz, detenga el servicio (puede encontrar información detallada en esta página). Para ello, siga estos pasos:

  1. Publique SERVICE_STOP_PENDING estado en SCM para indicar que el servicio va a estar inactivo

  2. Desinicializar o limpiar todo lo que el servicio estaba usando

  3. Publique el estado SERVICE_STOP en el gestor de control de servicios (SCM) para completar la operación de paro.

Si se detiene el servicio, asegúrese de revisar y examinar todos los identificadores abiertos que existan para las interfaces de dispositivo (puede que no haya ninguno) y límpielas.

La interfaz del dispositivo puede volver durante la instalación del dispositivo, habilitar o deshabilitar el dispositivo, volver a enumerar el dispositivo, reiniciar el sistema o durante otros escenarios no enumerados. Cuando vuelva la interfaz del dispositivo, el servicio se iniciará en función del registro de inicio del desencadenador.

Este flujo garantizará que el servicio se inicie a la llegada de una interfaz de dispositivo y se detenga cuando la última interfaz de dispositivo ya no esté presente.

Hay un ejemplo en GitHub que le guía por cómo un servicio puede aprovechar este flujo de eventos. El ejemplo se puede encontrar aquí: Ejemplo de servicio Win32.

Además, puede encontrar documentación útil sobre AddTrigger en la página AddService .