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 no definido. 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 AddService inf . Esto le permitirá crear e iniciar el servicio.

Agregue la configuración que hace que se inicie la demanda del servicio. 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 detalles 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.

Entorno de ejecución del servicio

Desde la perspectiva del entorno de ejecución, el primer paso para el servicio debe ser registrarse para las 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 la marca CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE para realizar el registro adecuado de las notificaciones de la interfaz de dispositivo.

Nota

Cuando se inicia un servicio, no puedes confiar en el hecho de que recibirás notificaciones de interfaz de dispositivo, ya que es posible que la notificación de llegada ya haya pasado, especialmente si una llegada de interfaz de dispositivo es 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 deshabilitan. Puede detectar 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 se 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 registrarse para recibir notificaciones y recuperar una lista de interfaces de dispositivo que ya están en el sistema. En ese caso, la interfaz del dispositivo se mostrará en la devolución de llamada de notificación y en la lista de interfaces de dispositivo.

Si desea interactuar con la interfaz del 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 consiste en registrarse en las notificaciones secundarias por identificador para recibir notificaciones de cambios de estado en el dispositivo, como intentos de consultar la eliminación del dispositivo o el dispositivo que desaparece. Esto se puede hacer mediante CM_Register_Notification con la marca CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE . Siguiendo las instrucciones que se indican en Registrarse 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 desaparezca, el controlador se puede liberar en consecuencia.

Se debe realizar un seguimiento de las llegadas y eliminaciones de la interfaz de dispositivo para que la eliminación de la última interfaz de dispositivo con la que el servicio quiera interactuar significa que se puede detener el servicio. 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 deja de funcionar

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

  3. Publicar SERVICE_STOP estado en SCM para completar la operación de detención

Si se detiene el servicio, asegúrese de comprobar si hay todos los identificadores abiertos existentes en las interfaces de dispositivo (puede que no haya ninguno) y limpielos.

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 desencadenará 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 .