//go:build windows package handlers import ( "fmt" "os" "os/exec" "path/filepath" "strings" "syscall" ) // installKneronWinUSBDriverHandler 呼叫 KneronPLUS SDK 的 libwdi wrapper 安裝 WinUSB driver。 // // 實作參考 edge-ai-platform installer/platform_windows.go 的 installKneronDriverViaSDK: // - 組 Python script 呼叫 kp.core.install_driver_for_windows(pid) 對三種 PID // - PowerShell Start-Process -Verb RunAs 提權(libwdi 要求 admin) // - 結果寫到 temp file 讓 Go 讀回來 func installKneronWinUSBDriverHandler(pythonBin string) error { if _, err := os.Stat(pythonBin); err != nil { return fmt.Errorf("python interpreter not found at %s: %w", pythonBin, err) } resultPath := filepath.Join(os.TempDir(), "visiona-local-driver-result.txt") _ = os.Remove(resultPath) // venv 根目錄 venvRoot := filepath.Dir(filepath.Dir(pythonBin)) pyScript := fmt.Sprintf(` import sys, os result_path = r'%s' try: kp_lib = os.path.join(r'%s', 'Lib', 'site-packages', 'kp', 'lib') if os.path.isdir(kp_lib): os.environ['PATH'] = kp_lib + ';' + os.environ.get('PATH', '') os.add_dll_directory(kp_lib) import kp results = [] for pid in [kp.ProductId.KP_DEVICE_KL520, kp.ProductId.KP_DEVICE_KL720, kp.ProductId.KP_DEVICE_KL720_LEGACY]: try: kp.core.install_driver_for_windows(pid) results.append(f"OK: {pid.name}") except Exception as e: results.append(f"SKIP: {pid.name}: {e}") with open(result_path, 'w') as f: f.write('\n'.join(results) + '\nDONE\n') except ImportError as e: with open(result_path, 'w') as f: f.write(f'ERROR: kp module not available: {e}\n') except Exception as e: with open(result_path, 'w') as f: f.write(f'ERROR: {e}\n') `, resultPath, venvRoot) scriptPath := filepath.Join(os.TempDir(), "visiona-local-install-usb-driver.py") if err := os.WriteFile(scriptPath, []byte(pyScript), 0o644); err != nil { return fmt.Errorf("write driver install script: %w", err) } defer os.Remove(scriptPath) elevateCmd := fmt.Sprintf( `Start-Process -FilePath '%s' -ArgumentList '"%s"' -Verb RunAs -Wait -WindowStyle Hidden`, pythonBin, scriptPath, ) cmd := exec.Command("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", elevateCmd) cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true, CreationFlags: 0x08000000} if out, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("driver 安裝需要系統管理員權限(UAC 可能被拒絕):%s", strings.TrimSpace(string(out))) } resultData, err := os.ReadFile(resultPath) _ = os.Remove(resultPath) if err != nil { return fmt.Errorf("driver 安裝已執行但無法讀取結果,請在裝置管理員確認或用 Zadig 手動安裝 https://zadig.akeo.ie/") } result := strings.TrimSpace(string(resultData)) if strings.Contains(result, "ERROR:") { return fmt.Errorf("driver 安裝失敗:%s", result) } return nil }