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) <noreply@anthropic.com>
This commit is contained in:
jim800121chen 2026-03-26 21:04:48 +08:00
parent 86b168c78a
commit 1a08a2599a

View File

@ -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