Udostępnij przez


Usługi Win32 współdziałające z urządzeniami

Idealna usługa Win32 zainstalowana za pośrednictwem usługi INF AddService , która współdziała z urządzeniami, działa podobnie jak w przypadku interakcji sterownika z urządzeniami. Sterownik jest ładowany i zwalniany w zależności od obecności urządzenia, a usługa Win32, która współdziała z urządzeniami, powinna postępować zgodnie z tym samym wzorcem uruchamiania i zatrzymywania w zależności od obecności urządzenia.

Usługi powinny być uruchamiane tylko wtedy, gdy interfejs urządzenia jest obecny i włączony do interakcji, a powinny być zatrzymywane, gdy interfejs urządzenia nie jest już włączony. Ten wzorzec projektu zapewnia niezawodną usługę, która minimalizuje niepożądane i niezdefiniowane zachowanie. Omówimy sposób projektowania usługi w celu przestrzegania tego wzorca.

Instalacja usługi

Aby zainstalować usługę, użyj dyrektywy INF AddService . Pozwoli to utworzyć i uruchomić usługę.

Dodaj ustawienie, które powoduje uruchomienie usługi na żądanie. Można to osiągnąć, ustawiając parametr StartType=0x3 , co powoduje uruchomienie wyzwalacza usługi.

Ostatnim krokiem w tej sekcji jest użycie dyrektywy AddTrigger w celu uruchomienia usługi po nadejściu interfejsu urządzenia (zobacz AddService, aby uzyskać więcej informacji na temat AddTrigger). Poniżej przedstawiono przykład użycia narzędzia 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

Należy pamiętać, że identyfikator HardwareId określony w elemecie DataItem jest opcjonalny i zazwyczaj wymagany tylko w przypadku używania interfejsu klasy ogólnej do określania zakresu wyzwalacza do bardziej szczegółowego urządzenia.

Środowisko uruchomieniowe usługi

Z perspektywy środowiska uruchomieniowego pierwszym krokiem dla usługi powinno być zarejestrowanie się w celu otrzymywania powiadomień interfejsu urządzenia. Instrukcje dotyczące tego, jak to zrobić, można znaleźć na tej stronie: Rejestrowanie powiadomień o przybyciu interfejsu urządzenia i usunięciu urządzenia.

W szczególności należy użyć CM_Register_Notification z flagą CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE , aby przeprowadzić odpowiednią rejestrację powiadomień interfejsu urządzenia.

Uwaga / Notatka

Podczas uruchamiania usługi nie można liczyć na to, że otrzymasz powiadomienia o interfejsie urządzenia, ponieważ informacja o jego przybyciu mogła już zostać otrzymana, zwłaszcza jeśli to przybycie interfejsu urządzenia jest przyczyną uruchamiania usługi. Zamiast tego należy uzyskać listę interfejsów urządzeń, aby sprawdzić, czy istnieją już interfejsy.

Po zarejestrowaniu powiadomień dotyczących interfejsów urządzeń otrzymasz powiadomienie o włączeniu nowych interfejsów urządzeń lub wyłączeniu istniejących interfejsów urządzeń. Ścieżkę interfejsu urządzenia można odnaleźć z wywołania zwrotnego powiadomień. Aby wykonać zapytanie dotyczące listy istniejących interfejsów urządzeń w celu sprawdzenia interfejsów urządzeń, które istniały przed rozpoczęciem działania usługi i zarejestrowaniem w celu otrzymywania powiadomień, możesz uzyskać listę interfejsów urządzeń za pośrednictwem interfejsów API, takich jak CM_Get_Device_Interface_List.

Uwaga / Notatka

Istnieje prawdopodobieństwo, że interfejs urządzenia pojawi się między rejestrowaniem powiadomień a pobieraniem listy interfejsów urządzeń już obecnych w systemie. W takim przypadku interfejs urządzenia zostanie wyświetlony zarówno w wywołaniu zwrotnym powiadomień, jak i na liście interfejsów urządzeń.

Jeśli chcesz wchodzić w interakcje z interfejsem urządzenia za pomocą interfejsów API we/wy, po znalezieniu żądanego interfejsu urządzenia otwórz uchwyt do interfejsu za pomocą polecenia CreateFile.

Następnym krokiem jest zarejestrowanie dodatkowych powiadomień dla poszczególnych uchwytów, aby otrzymywać powiadomienia o zmianach stanu urządzenia, takich jak próby zapytań o usunięcie urządzenia lub gdy urządzenie przestaje być dostępne. Można to zrobić przy użyciu CM_Register_Notification z flagą CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE . Postępując zgodnie z zasadami zawartymi w artykule Otrzymywanie powiadomień o nadejściu interfejsu urządzeniowego i usunięciu urządzenia, upewnij się, że gdy urządzenie jest usuwane, można odpowiednio zwolnić uchwyt.

Należy śledzić przybycia i usunięcia interfejsów urządzeń, aby usunięcie ostatniego interfejsu, z którym usługa może chcieć współpracować, oznaczało, że usługa może zostać zatrzymana. Po usunięciu ostatniego interfejsu zatrzymaj usługę (szczegółowe informacje można znaleźć na tej stronie). Można to zrobić, wykonując następujące czynności:

  1. Prześlij stan SERVICE_STOP_PENDING do SCM, aby wskazać, że usługa jest zatrzymywana.

  2. Zdezaktywuj/posprzątaj wszystko, z czego korzystała usługa.

  3. Przekazanie stanu SERVICE_STOP do systemu SCM w celu zakończenia operacji zatrzymania.

Jeśli usługa jest zatrzymywana, upewnij się, że sprawdzasz wszystkie istniejące otwarte uchwyty do interfejsów urządzeń (może ich nie być) i wyczyść je.

Interfejs urządzenia może wrócić podczas instalacji urządzenia, włączania/wyłączania urządzenia, ponownego wyliczania urządzenia, ponownego uruchamiania systemu lub w innych scenariuszach, których nie ma na liście. Po powrocie interfejsu urządzenia usługa zostanie uruchomiona na podstawie rejestracji uruchomienia wyzwalacza.

Ten przepływ zapewni, że usługa zostanie uruchomiona po nadejściu interfejsu urządzenia i zatrzyma się, gdy ostatni interfejs urządzenia nie jest już obecny.

W usłudze GitHub przedstawiono przykład, w jaki sposób usługa może korzystać z tego przepływu zdarzeń. Przykład można znaleźć tutaj: Przykład usługi Win32.

Ponadto na stronie AddService można znaleźć przydatną dokumentację dotyczącą dodatku AddTrigger.