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