Win32-Dienste, die mit Geräten interagieren

Ein idealer Win32-Dienst, der über INF AddService installiert wird und mit Geräten interagiert, verhält sich ähnlich wie ein Treiber mit Geräten interagiert. Je nach Vorhandensein eines Geräts wird ein Treiber geladen und entladen, und ein Win32-Dienst, der mit Geräten interagiert, sollte je nach Vorhandensein eines Geräts demselben Start - und Stoppmuster folgen.

Dienste sollten nur gestartet werden, wenn eine Geräteschnittstelle vorhanden ist und für die Interaktion mit aktiviert ist und beendet wird, wenn die Geräteschnittstelle nicht mehr aktiviert ist. Dieses Entwurfsmuster stellt einen stabilen Dienst sicher, der unerwünschtes und nicht definiertes Verhalten minimiert. Wir erfahren, wie ein Dienst so gestaltet werden sollte, dass er diesem Muster folgt.

Dienstinstallation

Verwenden Sie zum Installieren des Diensts die INF AddService-Direktive . Dadurch können Sie den Dienst erstellen und starten.

Fügen Sie die Einstellung hinzu, mit der der Dienst nach Bedarf gestartet wird. Dies kann erreicht werden, indem StartType=0x3 festgelegt wird, wodurch der Diensttrigger gestartet wird.

Der letzte Schritt in diesem Abschnitt besteht darin, die AddTrigger-Direktive zu verwenden, damit der Dienst gestartet wird, wenn eine Geräteschnittstelle eintrifft (weitere Informationen zu AddTrigger finden Sie unter AddService). Im Folgenden finden Sie ein Beispiel für die Verwendung von 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

Beachten Sie, dass die in DataItem angegebene HardwareId optional ist und in der Regel nur benötigt wird, wenn eine generische Klassenschnittstelle verwendet wird, um den Trigger auf ein spezifischeres Gerät zu beschränken.

Dienstruntime

Aus Laufzeitsicht sollte der erste Schritt für Ihren Dienst die Registrierung für Geräteschnittstellenbenachrichtigungen sein. Ausführliche Anleitungen dazu, wie Sie dies erreichen, finden Sie auf dieser Seite: Registrieren für die Benachrichtigung über die Ankunft der Geräteschnittstelle und Geräteentfernung.

Insbesondere sollten Sie CM_Register_Notification mit dem flag CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE verwenden, um die entsprechende Registrierung von Geräteschnittstellenbenachrichtigungen durchzuführen.

Hinweis

Wenn ein Dienst gestartet wird, können Sie sich nicht darauf verlassen, dass Sie Geräteschnittstellenbenachrichtigungen erhalten, da die Ankunftsbenachrichtigung möglicherweise bereits bestanden wurde, insbesondere wenn die Ankunft einer Geräteschnittstelle die Ursache für das Starten des Diensts ist. Stattdessen müssen Sie eine Liste der Geräteschnittstellen abrufen, um zu überprüfen, ob bereits Schnittstellen vorhanden sind.

Nachdem Sie sich für Benachrichtigungen für Geräteschnittstellen registriert haben, werden Sie darüber benachrichtigt, dass neue Geräteschnittstellen aktiviert oder vorhandene Geräteschnittstellen deaktiviert werden. Sie können den Pfad der Geräteschnittstelle über den Benachrichtigungsrückruf ermitteln. Um die Liste der vorhandenen Geräteschnittstellen abzufragen, um Geräteschnittstellen zu untersuchen, die vor dem Starten des Diensts vorhanden waren und für Benachrichtigungen registriert wurden, können Sie eine Liste der Geräteschnittstellen über APIs wie CM_Get_Device_Interface_List abrufen.

Hinweis

Es besteht die Möglichkeit, dass die Geräteschnittstelle zwischen der Registrierung für Benachrichtigungen und dem Abrufen einer Liste der Geräteschnittstellen eingeht, die bereits im System vorhanden sind. In diesem Fall wird die Geräteschnittstelle sowohl im Benachrichtigungsrückruf als auch in der Liste der Geräteschnittstellen aufgeführt.

Wenn Sie mit der Geräteschnittstelle mit E/A-APIs interagieren möchten, öffnen Sie ein Handle für die Schnittstelle über CreateFile, sobald Sie die gewünschte Geräteschnittstelle gefunden haben.

Der nächste Schritt besteht darin, sich für sekundäre Benachrichtigungen pro Handle zu registrieren, um über Zustandsänderungen am Gerät benachrichtigt zu werden, z. B. Versuche, das Gerät oder das Gerät abwesend abzufragen. Dies kann mithilfe von CM_Register_Notification mit dem flag CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE erfolgen. Befolgen Sie die Anleitung unter Registrieren für die Benachrichtigung über die Ankunft der Geräteschnittstelle und die Geräteentfernung , um sicherzustellen, dass das Ziehpunkt entsprechend freigegeben werden kann, wenn ein Gerät entfernt wird.

Ein- und Entfernungen der Geräteschnittstelle sollten nachverfolgt werden, damit das Entfernen der letzten Geräteschnittstelle, mit der der Dienst interagieren möchte, dazu führen kann, dass der Dienst beendet werden kann. Nachdem die letzte Schnittstelle entfernt wurde, beenden Sie Ihren Dienst (ausführliche Informationen finden Sie auf dieser Seite). Dies können Sie erreichen, indem Sie die folgenden Schritte ausführen:

  1. Posten sie SERVICE_STOP_PENDING Status an SCM, um anzugeben, dass der Dienst ausfällt.

  2. Aufheben der Initialisierung/sauber alles, was der Dienst verwendet hat

  3. Posten SERVICE_STOP Zustands in SCM, um den Beendigungsvorgang abzuschließen

Wenn der Dienst beendet wird, müssen Sie alle vorhandenen offenen Handles für Geräteschnittstellen (möglicherweise gibt es keine) überprüfen und durchlaufen und sie sauber.

Die Geräteschnittstelle kann entweder während der Geräteinstallation, der Geräteaktivierung/Deaktivierung, der erneuten Enumeration des Geräts, des Systemneustarts oder während anderer Szenarien, die nicht aufgeführt sind, zurückgegeben werden. Wenn die Geräteschnittstelle zurückkommt, wird der Dienst basierend auf der Startregistrierung des Triggers gestartet.

Dieser Flow stellt sicher, dass der Dienst beim Eintreffen einer Geräteschnittstelle gestartet und beendet wird, wenn die letzte Geräteschnittstelle nicht mehr vorhanden ist.

Es gibt ein Beispiel auf GitHub, in dem erläutert wird, wie ein Dienst diesen Ereignisfluss nutzen kann. Das Beispiel finden Sie hier: Win32-Dienstbeispiel.

Darüber hinaus finden Sie nützliche Dokumentation zu AddTrigger auf der AddService-Seite .