다음을 통해 공유


디바이스와 상호 작용하는 Win32 서비스

디바이스와 상호 작용하는 INF AddService 를 통해 설치된 이상적인 Win32 서비스는 드라이버디바이스와 상호 작용하는 방식과 유사하게 작동합니다. 디바이스의 존재에 따라 드라이버가 로드되고 언로드되며, 디바이스와 상호 작용하는 Win32 서비스는 디바이스의 존재에 따라 이와 동일한 시작중지 패턴을 따라야 합니다.

서비스는 디바이스 인터페이스가 있고 디바이스 인터페이스가 더 이상 사용하도록 설정되지 않은 경우 상호 작용하고 중지할 수 있는 경우에만 시작해야 합니다. 이 디자인 패턴은 원치 않는 동작과 정의되지 않은 동작을 최소화하는 강력한 서비스를 보장합니다. 이 패턴을 따르도록 서비스를 설계하는 방법을 살펴보겠습니다.

서비스 설치

서비스를 설치하려면 INF AddService 지시문을 사용합니다. 이렇게 하면 서비스를 만들고 시작할 수 있습니다.

서비스 수요 시작을 만드는 설정을 추가합니다. 이 작업은 서비스 트리거를 시작하게 하는 StartType=0x3 설정하여 수행할 수 있습니다.

이 섹션의 마지막 단계는 AddTrigger 지시문을 사용하여 디바이스 인터페이스가 도착할 때 서비스를 시작하도록 하는 것입니다(AddTrigger에 대한 자세한 내용은 AddService 참조). 다음은 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

DataItem에 지정된 HardwareId는 선택 사항이며 일반적으로 일반 클래스 인터페이스를 사용하여 트리거를 보다 구체적인 디바이스에 scope 경우에만 필요합니다.

서비스 런타임

런타임 관점에서 서비스의 첫 번째 단계는 디바이스 인터페이스 알림을 등록하는 것입니다. 이 작업을 수행하는 방법에 대한 규범적인 지침은 디바이스 인터페이스 도착 및 디바이스 제거 알림 등록 페이지에서 찾을 수 있습니다.

특히 CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE 플래그와 함께 CM_Register_Notification 사용하여 디바이스 인터페이스 알림의 적절한 등록을 수행해야 합니다.

참고

서비스를 시작할 때 도착 알림이 이미 전달되었을 수 있으므로 디바이스 인터페이스 알림을 받게 될 것이라는 사실에 의존할 수 없습니다. 특히 디바이스 인터페이스 도착이 서비스 시작의 원인인 경우입니다. 대신 이미 인터페이스가 있는 경우 검사 디바이스 인터페이스 목록을 가져와야 합니다.

디바이스 인터페이스에 대한 알림을 등록하면 새 디바이스 인터페이스를 사용하도록 설정하거나 기존 디바이스 인터페이스를 사용하지 않도록 설정하는 것에 대한 알림이 표시됩니다. 알림 콜백에서 디바이스 인터페이스 경로를 검색할 수 있습니다. 기존 디바이스 인터페이스 목록을 쿼리하여 서비스가 시작되고 알림을 등록하기 전에 존재하는 디바이스 인터페이스를 검사하려면 CM_Get_Device_Interface_List 같은 API를 통해 디바이스 인터페이스 목록을 가져올 수 있습니다.

참고

알림을 등록하고 시스템에 이미 있는 디바이스 인터페이스 목록을 검색하는 사이에 디바이스 인터페이스가 도착할 가능성이 있습니다. 이 경우 디바이스 인터페이스는 알림 콜백과 디바이스 인터페이스 목록 모두에 나열됩니다.

I/O API를 사용하여 디바이스 인터페이스와 상호 작용하려는 경우 원하는 디바이스 인터페이스를 찾은 후 CreateFile을 통해 인터페이스에 대한 핸들을 엽니다.

다음 단계는 보조 처리당 알림을 등록하여 디바이스 제거 시도 또는 디바이스 제거 시도와 같은 디바이스의 상태 변경에 대한 알림을 받는 것입니다. 이 작업은 CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE 플래그와 함께 CM_Register_Notification 사용하여 수행할 수 있습니다. 디바이스 인터페이스 도착 및 디바이스 제거 알림 등록의 지침에 따라 디바이스가 사라지면 핸들을 적절하게 해제할 수 있습니다.

서비스가 상호 작용할 수 있는 마지막 디바이스 인터페이스의 제거가 서비스를 중지할 수 있도록 디바이스 인터페이스 도착 및 제거를 추적해야 합니다. 마지막 인터페이스가 제거되면 서비스를 중지합니다(자세한 내용은 이 페이지에서 찾을 수 있습니다). 이 작업은 다음 단계를 수행하여 수행할 수 있습니다.

  1. SCM에 SERVICE_STOP_PENDING 상태를 게시하여 서비스가 중단됨을 나타냅니다.

  2. 서비스에서 사용하던 모든 항목을 초기화/클린

  3. SERVICE_STOP 상태를 SCM에 게시하여 중지 작업을 완료합니다.

서비스가 중지되는 경우 에 대해 검사 기존 열려 있는 모든 핸들을 디바이스 인터페이스(없을 수 있음)로 이동하여 클린 합니다.

디바이스 인터페이스는 디바이스 설치 중, 디바이스 사용/사용 안 함, 디바이스 다시 열거, 시스템 다시 부팅 중 또는 나열되지 않은 다른 시나리오 중에 돌아올 수 있습니다. 디바이스 인터페이스가 다시 돌아오면 트리거 시작 등록에 따라 서비스가 트리거됩니다.

이 흐름은 서비스가 디바이스 인터페이스의 도착 시 시작되고 마지막 디바이스 인터페이스가 더 이상 없을 때 중지되도록 합니다.

GitHub에는 서비스가 이러한 이벤트 흐름을 활용하는 방법을 안내하는 샘플이 있습니다. 샘플은 Win32 서비스 샘플에서 찾을 수 있습니다.

또한 AddService 페이지에서 AddTrigger에 대한 유용한 설명서를 찾을 수 있습니다.