同樣的禁用 USB 程式碼,在 WinForms 應用程式中正常,放入 Windows Service 後失敗,無異常拋出,設備不禁用。
服務預設以「Local Service」或「Network Service」帳號運行,權限不足,無法存取裝置管理介面 (SetupAPI / Device Installation APIs) 執行硬體變更操作。
// ProjectInstaller.cs (設計器生成的類)
public ProjectInstaller() {
InitializeComponent();
// 關鍵:設定服務帳號為 LocalSystem
this.serviceProcessInstaller1.Account = ServiceAccount.LocalSystem;
this.serviceInstaller1.StartType = ServiceStartMode.Automatic;
}
using System.ServiceProcess;
public static void InstallService(string exePath, string serviceName) {
var psi = new ServiceProcessInstaller { Account = ServiceAccount.LocalSystem };
var si = new ServiceInstaller {
ServiceName = serviceName,
DisplayName = "USB Blocker Service",
StartType = ServiceStartMode.Automatic
};
var assemblyInstaller = new AssemblyInstaller(exePath, null) {
Installers = { psi, si }
};
var state = new System.Collections.Hashtable();
assemblyInstaller.Install(state);
assemblyInstaller.Commit(state);
}
sc create "USBBlocker" binPath= "C:\Path\USBBlocker.exe" start= auto obj= "LocalSystem"
sc start "USBBlocker"
[DllImport("setupapi.dll", SetLastError = true)]
static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid, uint Enumerator, IntPtr hwndParent, uint Flags);
[DllImport("setupapi.dll", SetLastError = true)]
static extern bool SetupDiSetClassInstallParams(
IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData,
ref SP_PROPCHANGE_PARAMS ClassInstallParams, uint ClassInstallParamsSize);
[DllImport("setupapi.dll", SetLastError = true)]
static extern bool SetupDiCallClassInstaller(
uint InstallFunction, IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData);
// DIF_PROPERTYCHANGE = 0x12
// DICS_DISABLE = 0x00000003
// DICS_FLAG_GLOBAL = 0x00000001
| 方案 | 優點 | 缺點 |
|---|---|---|
| 服務 + LocalSystem | 簡單、單一程序 | 高權限、安全風險 |
| 服務 + 呼叫用戶端代理 | 權限分離、用戶確認 | 需用戶登入、雙進程 |
| 群組策略 / MDM 禁用 USB | 企業級、無代碼 | 靈活性低 |
| 驅動層過濾 (Upper Filter Driver) | 最底層、最徹底 | 開發極其複雜、需簽名 |