與裝置互動的 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 是選擇性的,通常只有在使用泛型類別介面將觸發程式限定為更特定的裝置時才需要。
服務執行階段
從運行時間的觀點來看,服務的第一個步驟應該是註冊裝置介面通知。 如需如何完成這項操作的規範指引,請參閱此頁面: 註冊裝置介面抵達和移除裝置的通知。
特別是,您應該使用 CM_Register_Notification 搭配 CM_NOTIFY_FILTERY_TYPE_DEVICEINTERFACE 旗標來完成適當的裝置介面通知註冊。
注意
當服務啟動時,您無法依賴將接收裝置介面通知的事實,因為抵達通知可能已經通過,特別是當裝置介面抵達是服務啟動的原因時。 相反地,您必須取得裝置介面清單,以檢查是否有已有介面存在。
註冊裝置介面的通知之後,您會收到已啟用新裝置介面或停用現有裝置介面的通知。 您可以從通知回呼探索裝置介面路徑。 若要查詢現有裝置介面的清單,以檢查服務啟動並註冊通知之前存在的裝置介面,您可以透過 api 取得裝置介面清單,例如 CM_Get_Device_Interface_List。
注意
裝置介面有機會在註冊通知和擷取系統上已有的裝置介面清單之間抵達。 在此情況下,裝置介面會同時列在通知回呼和裝置介面清單中。
如果您想要與裝置介面與 I/O API 互動,一旦您找到所需的裝置介面,請透過 CreateFile 開啟介面的句柄。
下一個步驟是註冊次要個別句柄通知,以取得裝置狀態變更的通知,例如嘗試查詢移除裝置或裝置離開。 這可以使用 CM_Register_Notification 搭配 CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE 旗標來完成。 遵循 註冊裝置介面抵達和裝置移除通知 的指引,可確保裝置離開時,可以據以釋放句柄。
應該追蹤裝置介面抵達和移除,以便移除服務可能想要與其互動的最後一個裝置介面,表示可以停止服務。 拿掉最後一個介面之後, 您可以在此頁面找到 您的服務 (詳細資訊) 。 您可以遵循下列步驟來完成此作業:
將 SERVICE_STOP_PENDING 狀態張貼至 SCM,以指出服務已關閉
取消初始化/清除服務所使用的一切
將 SERVICE_STOP 狀態張貼至 SCM 以完成停止作業
如果服務停止,請務必檢查並流覽所有現有的開啟句柄到裝置介面, (可能沒有任何) 並清除它們。
裝置介面可以在裝置安裝、裝置啟用/停用、裝置重新列舉、系統重新啟動或未列出的其他案例期間返回。 當裝置介面傳回時,服務會根據其觸發程式啟動註冊來啟動。
此流程可確保服務會在裝置介面的抵達時啟動,並在最後一個裝置介面不存在時停止。
程式代碼範例 & 相關連結
GitHub 上有一個範例,會逐步解說服務如何運用此事件流程。 您可以在這裡找到此範例: Win32 服務範例。
此外,您可以在 AddService 頁面上找到有關 AddTrigger 的實用檔。