## 现象 Windows 上若 OS 拒绝低层键盘 hook 安装(\`SetWindowsHookExW(WH_KEYBOARD_LL)\` 因 UAC / 第三方安全软件 / 防御性策略而长期 starting),OpenLess 主窗口**永久卡在 \"正在启动\" 灰屏**,UI 永远不出来——用户点 OpenLess.exe 后看到一个空 shell,没法进设置改 hotkey、没法看错误。 ## 复现 人为复现路径: 1. Windows 上的反作弊/EDR 安全软件 block 第三方进程的 keyboard hook 2. 或测试用 \`SetWindowsHookExW\` mock 永远返回 NULL 3. 启动 OpenLess 4. **观察**:UI 卡 StartupShell 灰屏不动,无超时不弹错误 实际场景:用户报反馈"打开 OpenLess 看到一片空白不动"——根因可能就是这条。 ## 根因 `App.tsx:60` Windows 启动 gate 用无限轮询查 hotkey status: \`\`\`tsx const pollHotkeyStatus = async () => { while (!cancelled) { const status = await getHotkeyStatus(); if (cancelled) return; if (status.state !== 'starting') { setGate('ready'); return; } await new Promise(resolve => window.setTimeout(resolve, 200)); } }; \`\`\` - 只在 \`state !== 'starting'\` 才 break - 后端 \`hotkey_supervisor_loop\` 永远 starting(hook 安装失败但持续重试)→ 前端永远 200ms 一次 ping,永不退出 - catch 分支会兜底但 try 内 `getHotkeyStatus()` 不抛错只回 'starting' 时,永远进不去 catch ## 影响 - **平台**:仅 Windows(macOS / Linux 走不同 gate 逻辑) - **频率**:边缘场景(依赖第三方安全软件配置),但当下没有任何超时保护 - **用户损失**:完全无法使用 OpenLess,且看不到错误信息 ## 建议 fix 加最大轮询次数 + 超时 fallback: \`\`\`tsx const MAX_POLL = 50; // 50 * 200ms = 10s let attempts = 0; while (!cancelled && attempts < MAX_POLL) { attempts++; const status = await getHotkeyStatus(); if (cancelled) return; if (status.state !== 'starting') { setGate('ready'); return; } await new Promise(resolve => window.setTimeout(resolve, 200)); } // 超时强 setGate('ready'),让用户进 Permissions 页看错误 if (!cancelled) { console.warn('[startup] hotkey gate timed out after 10s'); setGate('ready'); } \`\`\` `Permissions` 页应该已经能显示 hotkey_status 的 lastError + 引导用户检查权限/安全软件。先让用户**能看到**这个页面。
Activity
Merge pull request #172 from appergb/fix/issue-163-windows-startup-ga…
fix(windows): 启动 gate pollHotkeyStatus 加 10s 超时 (closes #163)
fix(windows): 静默启动 #468 最后一公里 - 前端兜底 (#474)