From 1a08a2599ae04649b27ed57792bb2eea6f912992 Mon Sep 17 00:00:00 2001 From: jim800121chen Date: Thu, 26 Mar 2026 21:04:48 +0800 Subject: [PATCH] fix: run kp driver install elevated via UAC libwdi requires admin privileges to install WinUSB driver. Previously the script ran as the current user which silently succeeded but the driver was not actually installed. Now runs the Python script elevated via Start-Process -Verb RunAs, which triggers a UAC prompt. Also adds os.add_dll_directory() to ensure kp can find libwdi.dll, and writes results to a temp file since elevated process output is not capturable. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../installer/platform_windows.go | 75 ++++++++++++------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/edge-ai-platform/installer/platform_windows.go b/edge-ai-platform/installer/platform_windows.go index 18b7a48..862e23e 100644 --- a/edge-ai-platform/installer/platform_windows.go +++ b/edge-ai-platform/installer/platform_windows.go @@ -169,46 +169,71 @@ func installUSBDriver(installDir string) error { // installKneronDriverViaSDK uses the KneronPLUS SDK's built-in libwdi to // install WinUSB driver for all known Kneron devices. Must be called after // the Python venv with kp module is set up. +// libwdi requires admin privileges, so this runs elevated via UAC. func installKneronDriverViaSDK(installDir string) error { venvPython := filepath.Join(installDir, "venv", "Scripts", "python.exe") if _, err := os.Stat(venvPython); err != nil { return fmt.Errorf("Python venv not found, cannot install driver") } - // Use kp.core.install_driver_for_windows() for each known product ID - // KL520=0x100, KL720=0x720, KL720_LEGACY=0x200 - script := ` -import sys + resultPath := filepath.Join(os.TempDir(), "edge-ai-driver-result.txt") + os.Remove(resultPath) + + // Python script that installs WinUSB driver for all Kneron devices + pyScript := fmt.Sprintf(` +import sys, os +result_path = r'%s' try: + # Ensure kp can find its DLLs + kp_lib = os.path.join(r'%s', 'venv', '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) - print(f"OK: driver installed for {pid.name}") + results.append(f"OK: {pid.name}") except Exception as e: - print(f"SKIP: {pid.name}: {e}") - print("DONE") -except ImportError: - print("ERROR: kp module not available") - sys.exit(1) -` - cmd := exec.Command(venvPython, "-c", script) - cmd.Dir = installDir - // Ensure kp can find its DLLs - cmd.Env = append(os.Environ(), - fmt.Sprintf("PATH=%s;%s;%s", - filepath.Join(installDir, "venv", "Lib", "site-packages", "kp", "lib"), - installDir, - os.Getenv("PATH"))) + 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, installDir) - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("WinUSB driver install via KneronPLUS SDK failed: %s — please install manually using Zadig (https://zadig.akeo.ie/)", strings.TrimSpace(string(out))) + // Write Python script to temp file + scriptPath := filepath.Join(os.TempDir(), "edge-ai-install-usb-driver.py") + if err := os.WriteFile(scriptPath, []byte(pyScript), 0644); err != nil { + return fmt.Errorf("failed to write driver install script: %w", err) + } + defer os.Remove(scriptPath) + + // Run elevated via UAC (libwdi requires admin) + elevateCmd := fmt.Sprintf( + `Start-Process -FilePath '%s' -ArgumentList '"%s"' -Verb RunAs -Wait -WindowStyle Hidden`, + venvPython, scriptPath, + ) + cmd := exec.Command("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", elevateCmd) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("WinUSB driver install requires administrator permission — please install manually using Zadig (https://zadig.akeo.ie/). Details: %s", strings.TrimSpace(string(out))) } - output := string(out) - if strings.Contains(output, "ERROR:") { - return fmt.Errorf("WinUSB driver install failed: %s — please install manually using Zadig (https://zadig.akeo.ie/)", strings.TrimSpace(output)) + // Read result + resultData, err := os.ReadFile(resultPath) + os.Remove(resultPath) + if err != nil { + return fmt.Errorf("WinUSB driver install completed but could not read result — please verify in Device Manager or install manually using Zadig (https://zadig.akeo.ie/)") + } + + result := strings.TrimSpace(string(resultData)) + if strings.Contains(result, "ERROR:") { + return fmt.Errorf("WinUSB driver install failed: %s — please install manually using Zadig (https://zadig.akeo.ie/)", result) } return nil