diff --git a/lib/setup/driver_install.dart b/lib/setup/driver_install.dart index 232bd42..ad0b457 100644 --- a/lib/setup/driver_install.dart +++ b/lib/setup/driver_install.dart @@ -6,13 +6,11 @@ import '../utils/command_runner.dart'; /// /// - macOS:CUPS 过滤器 pkg(dmg 内置),已装判断 = /Library/Printers/HiTi 存在, /// 安装 = 挂载 dmg → osascript 提权 installer → 卸载卷 -/// - Windows:HiTi 官方驱动 exe(assets/drivers/*.exe 内置),UAC 提权运行; -/// 已装判断 = 我们自己的注册表标记(HKCU\Software\zax\desktop-plugin, -/// 系统级驱动安装状态无统一可查标志,安装成功后写标记最可靠) +/// - Windows:HiTi 官方驱动整目录 zip 内置,已装判断 = pnputil 枚举驱动商店 +/// (实时校验,安装器壳提前退出不会误判),安装 = 解压 → UAC 提权 Setup64 → +/// pnputil 校验通过才算成功 class DriverInstall { static const installedMarker = '/Library/Printers/HiTi'; - static const _winMarkKey = r'HKCU\Software\zax\desktop-plugin'; - static const _winMarkValue = 'HiTiDriverInstalled'; static bool get isSupported => Platform.isMacOS || Platform.isWindows; @@ -22,15 +20,14 @@ class DriverInstall { return false; // Windows 走异步 queryInstalled(注册表查询需要子进程) } - /// Windows:异步查询安装标记。 + /// Windows:pnputil 实时校验驱动商店(安装器是自解压壳、可能假成功, + /// 注册表标记会被失败的安装误写,故以系统驱动商店为唯一真源)。 static Future queryInstalled() async { if (!Platform.isWindows) return isInstalled(); - final out = await runCommand( - 'reg', - ['query', _winMarkKey, '/v', _winMarkValue], - tolerateExit: true, - ); - return out.contains('0x1'); + final drivers = await runCommand('pnputil', ['/enum-drivers'], + tolerateExit: true, timeoutMs: 60000); + final lower = drivers.toLowerCase(); + return lower.contains('cs2xxhcd') || lower.contains('htitahcd') || lower.contains('hiti'); } /// 内置驱动安装包的文件系统路径;未打包携带返回 null。 @@ -135,10 +132,11 @@ class DriverInstall { throw StateError('驱动包内未找到安装程序(Setup64.exe)'); } log('开始安装 HiTi 打印机驱动(请在 UAC 弹窗中确认,安装向导可能需要点几次"下一步")…'); - // -Verb RunAs 触发 UAC;-Wait 等安装程序退出(用户取消 UAC 时 PowerShell 报错) + // 注意:HiTi 的 Setup64 是自解压壳(InstallShield 类),-Wait 等的是壳进程, + // 内层安装向导可能仍在运行——安装是否成功必须以后续的驱动校验为准 final script = 'Start-Process -FilePath "$setup" -Verb RunAs -Wait'; await runCommand('powershell', ['-Command', script], timeoutMs: 600000); - log('驱动安装程序已退出'); + log('安装程序已退出,正在校验驱动是否装入系统…'); } finally { // 3. 清理临时目录(失败不影响安装结果) try { @@ -146,10 +144,19 @@ class DriverInstall { } catch (_) {} } - // 4. 写安装标记(我们自己的注册表键;0x1 = 已装) - await runCommand('reg', - ['add', _winMarkKey, '/v', _winMarkValue, '/t', 'REG_DWORD', '/d', '1', '/f']); - log('已记录驱动安装状态'); + // 4. 校验:驱动是否真的进了驱动商店(pnputil 枚举,匹配 htitahcd/CS2xx) + await Future.delayed(const Duration(seconds: 3)); // 给安装收尾一点时间 + final drivers = await runCommand('pnputil', ['/enum-drivers'], + tolerateExit: true, timeoutMs: 60000); + final lower = drivers.toLowerCase(); + final installed = lower.contains('cs2xxhcd') || lower.contains('htitahcd') || lower.contains('hiti'); + if (!installed) { + throw StateError( + '驱动校验未通过:系统中未发现 HiTi 驱动(安装器可能未真正完成,请重试,' + '或手动运行驱动包 CS2xx 目录内的 Setup64.exe 完成安装)'); + } + log('校验通过:HiTi 驱动已装入系统'); + log('驱动安装完成——请拔掉打印机 USB 重新插上(驱动绑定需要设备重新枚举),然后重新检测'); } static String? _findFileDeep(String root, String lowerName) {