Windows 7/Vista 大幅改進後台處理,核心挑戰:
Win7 採用多重機制回應:服務要求權限、服務 SID、延遲自動啟動、觸發啟動、排程任務條件設定。
Tools → Options → Projects and Solutions → VC++ Directories:Executable files 加 %Windows7SDK%\v7.0\BinInclude files 加 %Windows7SDK%\v7.0\IncludeLibrary files 加 %Windows7SDK%\v7.0\Lib
C:\FromUSB:USB 映像複製目的地ToCopy:映像來源資料夾範例服務:偵測 USB 大容量儲存裝置插入,自動複製 ToCopy 內容至 C:\FromUSB。展示觸發啟動與最小權限技術。
使用 ChangeServiceConfig2 Win32 API。
SERVICE_REQUIRED_PRIVILEGES_INFO reqPriv = {0};
reqPriv.pmszRequiredPrivileges = SE_CHANGE_NOTIFY_NAME L"\0"; // 僅保留遍歷檢查權限
ChangeServiceConfig2(hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, &reqPriv);
// 裝置介面觸發資料
LPCWSTR devStr = L"USBSTOR\\GenDisk";
SERVICE_TRIGGER_SPECIFIC_DATA_ITEM devData = {0};
devData.dwDataType = SERVICE_TRIGGER_DATA_TYPE_STRING;
devData.cbData = (wcslen(devStr)+1)*sizeof(WCHAR);
devData.pData = (PBYTE)devStr;
// 觸發器定義
SERVICE_TRIGGER trigger = {0};
trigger.dwTriggerType = SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL;
trigger.dwAction = SERVICE_TRIGGER_ACTION_SERVICE_START;
trigger.pTriggerSubtype = (GUID*)&GUID_USBDevice;
trigger.cDataItems = 1;
trigger.pDataItems = &devData;
// 觸發資訊
SERVICE_TRIGGER_INFO triggerInfo = {0};
triggerInfo.cTriggers = 1;
triggerInfo.pTriggers = &trigger;
ChangeServiceConfig2(hService, SERVICE_CONFIG_TRIGGER_INFO, &triggerInfo);
在 RegisterServiceForm 加入按鈕事件:
// C#
btnRegisterTriggerStart_Click: AddService(); ServiceControl.SetServiceTriggerStartOnUSBArrival(ServiceName);
btnRemovePrivileges_Click: ServiceControl.RemoveAllPrivilegesFromService(ServiceName);
UsbCopyService 中 OnStart 判斷是否為觸發啟動:
// C#
protected override void OnStart(string[] args) {
if (ServiceControl.IsServiceTriggerStart(ServiceName)) {
ThreadPool.QueueUserWorkItem(_ => { DoWork(); Stop(); }); // 執行一次即停止
} else {
_timer = new Timer(_ => DoWork(), null, 0, 5000); // 輪詢模式
}
}
SeChangeNotifyPrivilegesc qtriggerinfo UsbCopyService 驗證配置 → 插入 USB → 服務自動啟動、複製、關閉 → sc queryex UsbCopyService 確認停止 → 刪除服務
透過觸發啟動機制,服務僅在真正需要時運行;移除非必要權限縮減攻擊面。完整範例包含 USB 複製服務與 Weather Updater 服務兩個示範專案。