Freigeben über


Win32-Dienste, die mit Geräten interagieren

Ein idealer Win32-Dienst, der über INF AddService installiert ist, der mit Geräten interagiert, verhält sich ähnlich wie eine Interaktion eines Treibers mit Geräten. 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 das gleiche Start - und Stoppmuster aufweisen.

Dienste sollten nur gestartet werden, wenn eine Geräteschnittstelle vorhanden und aktiviert ist, und beendet werden, wenn die Geräteschnittstelle nicht mehr aktiviert ist. Dieses Entwurfsmuster stellt einen robusten Dienst sicher, der unerwünschtes und nicht definiertes Verhalten minimiert. Wir werden durchgehen, wie ein Dienst so konzipiert werden sollte, dass es diesem Muster folgt.

Dienstinstallation

Verwenden Sie die INF-AddService-Direktive , um den Dienst zu installieren. Auf diese Weise können Sie den Dienst erstellen und starten.

Fügen Sie die Einstellung hinzu, die den Dienst als "Service on Demand" startet. Dies kann durch Festlegen von StartType=0x3 erreicht werden, wodurch der Diensttrigger gestartet wird.

Der letzte Schritt in diesem Abschnitt besteht darin, die AddTrigger-Direktive zu verwenden, um den Dienst zu starten, wenn eine Geräteschnittstelle eingeht (weitere Details 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 erforderlich ist, wenn sie eine generische Klassenschnittstelle verwenden, um den Trigger auf ein spezifischeres Gerät zu beschränken.

Dienstlaufzeit

Aus Laufzeitsicht sollte der erste Schritt für Ihren Dienst die Registrierung für Geräteschnittstellenbenachrichtigungen sein. Empfohlene Vorgehensweisen dazu finden Sie auf dieser Seite: Registrierung für Benachrichtigungen über die Ankunft der Geräteschnittstelle und das Entfernen von Geräten.

Insbesondere sollten Sie CM_Register_Notification mit dem CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE Flag 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 Benachrichtigungen über die Geräteschnittstelle erhalten, da die Ankunftsbenachrichtigung möglicherweise bereits erfolgt ist, insbesondere dann, wenn das Eintreffen einer Geräteschnittstelle der Grund für das Starten des Dienstes 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 informiert, dass neue Geräteschnittstellen aktiviert oder vorhandene Geräteschnittstellen deaktiviert werden. Sie können den Geräteschnittstellenpfad aus dem Benachrichtigungsrückruf ermitteln. Um die Liste der vorhandenen Geräteschnittstellen abzufragen, um Geräteschnittstellen zu untersuchen, die vorhanden waren, bevor der Dienst gestartet und für Benachrichtigungen registriert wurde, 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 bereits im System vorhandenen Geräteschnittstellen ankommt. 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 über CreateFile, nachdem 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 des Geräts benachrichtigt zu werden, wie etwa bei Versuchen, das Gerät abzufragen oder zu entfernen, oder wenn das Gerät nicht mehr verfügbar ist. Dies kann mithilfe von CM_Register_Notification mit dem CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE-Flag erfolgen. Beim Befolgen der Anleitung unter Registrierung für die Benachrichtigung über das Eintreffen von Geräteschnittstellen und das Entfernen von Geräten wird sichergestellt, dass der Zugriff entsprechend freigegeben werden kann, wenn ein Gerät entfernt wird.

Geräteschnittstelleneinkünfte und Entfernungen sollten nachverfolgt werden, damit das Entfernen der letzten Geräteschnittstelle, mit der der Dienst interagieren möchte, bedeutet, dass der Dienst beendet werden kann. Nachdem die letzte Schnittstelle entfernt wurde, beenden Sie Ihren Dienst (detaillierte Informationen finden Sie auf dieser Seite). Dies kann mit den folgenden Schritten erreicht werden:

  1. Teilen Sie den Zustand SERVICE_STOP_PENDING dem SCM mit, um anzuzeigen, dass der Dienst gestoppt wird.

  2. Deinitialisieren/Bereinigen aller Ressourcen, die der Dienst verwendet hat

  3. Um den Stoppvorgang abzuschließen, den Status SERVICE_STOP an SCM übermitteln.

Wenn der Dienst beendet wird, stellen Sie sicher, dass Sie alle vorhandenen offenen Handles für Geräteschnittstellen überprüfen und durchlaufen (möglicherweise keine vorhanden sind), und bereinigen Sie sie.

Die Geräteschnittstelle kann entweder während der Geräteinstallation, der Aktivierung oder Deaktivierung des Geräts, der erneuten Aufzählung des Geräts, des Systemneustarts oder während anderer nicht aufgeführter Szenarien verfügbar sein. Wenn die Geräteschnittstelle zurückkehrt, wird der Dienst basierend auf seiner Startauslöser-Registrierung gestartet.

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

Es gibt ein Beispiel auf GitHub, das durchläuft, wie ein Dienst diesen Ereignisfluss nutzen kann. Das Beispiel finden Sie hier: Win32 Service Sample.

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