fix(windows): NSIS 安装包注册 TSF DLL + local-asr RAM 真正归还#279
Conversation
## 现象
1.2.15 起在 Settings 页"Windows 输入法后端"出现 Pill「不可用」。`get_windows_ime_status()`
查 HKLM 注册表四件套(COM CLSID + TSF LanguageProfile + 三个 Category),缺一即报 NotInstalled。
## 根因
- MSI 通过 wix/openless-ime.wxs 的 RegisterOpenLessIme* CustomAction 跑 regsvr32 → 注册齐全。
- NSIS 包既没把 OpenLessIme.dll 打进去(wxs.componentRefs 是 MSI-only),也没 hook 跑
regsvr32 → 用 setup.exe 安装的用户、走 updater 自动升级的存量用户全部命中"不可用"。
- 由于 updater latest-windows-x86_64.json 是 NSIS pass 写的,老 MSI 用户每次更新后也
会被替换为没 TSF 的 NSIS 版本。
## 修复
- 加 src-tauri/installer.nsh:NSIS_HOOK_POSTINSTALL/PREUNINSTALL 跑 regsvr32 注册/反注册。
- bundle.resources map 把 OpenLessIme.dll 拷贝到 $INSTDIR\tsf-ime\OpenLessIme.dll
(target 路径避开 wxs File 已声明的 windows-ime\x64\,避免 MSI component 路径冲突)。
- bundle.windows.nsis.installMode = "perMachine",让 NSIS 以管理员身份运行(写 HKLM 必需)。
- CI 在 build native dll 后把真 dll 复制到 src-tauri/openless-ime-payload/x64/OpenLessIme.dll;
仓库 commit 0 字节占位文件,让本地 mac 端 tauri build 也能 resolve resources 路径。
- build-mac.sh 与 Linux build 步骤加 --config '{"bundle":{"resources":{}}}' 跳过 Windows-only
的 dll 占位,避免污染 mac .app / Linux .deb/.rpm/.AppImage。
## Trade-off
- NSIS perMachine 升级需要 UAC,老 currentUser 用户首次升级时多一次 UAC 提示。
- MSI 包里 dll 会有两份(wxs File + bundle.resources),磁盘冗余 ~几百 KB,无功能影响。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5aec74653b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "icons/icon.ico" | ||
| ], | ||
| "resources": { | ||
| "openless-ime-payload/x64/OpenLessIme.dll": "tsf-ime/OpenLessIme.dll" |
There was a problem hiding this comment.
Register the 32-bit TSF DLL for NSIS installs
For NSIS/updater installs this resource map only packages the x64 DLL, and the new hook only runs regsvr32 against that one file. However inspect_windows_ime_registration() explicitly requires both the 64-bit COM key and the WOW64 32-bit COM key (KEY_WOW64_32KEY) before reporting the backend as installed, matching the MSI flow that registers both OpenLessImeDllX64 and OpenLessImeDllX86. As a result, users installed via NSIS will still see the Windows IME backend as broken/not available with “OpenLess 32-bit COM registration is missing,” so the intended fix does not take effect for the updater path.
Useful? React with 👍 / 👎.
Codex review 发现:windows_ime_profile.rs::inspect_windows_ime_registration() 同时
用 KEY_WOW64_64KEY 和 KEY_WOW64_32KEY 两次检查 HKLM\Software\Classes\CLSID\{...}\
InprocServer32,少了任一边就返回 RegistrationBroken("OpenLess 32-bit COM
registration is missing")。MSI 流程通过 wxs 同时跑了 64-bit 和 SysWOW64\regsvr32
注册两份;之前的 NSIS hook 只注册了 x64,所以 NSIS / updater 用户依然在 Settings
页看到「不可用」。
修复:
- bundle.resources 拆出 x64 / x86 两份 dll target;x64 → tsf-ime\x64,x86 → tsf-ime\x86
- installer.nsh PostInstall/PreUninstall 增加 x86 分支,
x86 用 $WINDIR\SysWOW64\regsvr32.exe(写 KEY_WOW64_32KEY 必需)
- CI Build Windows IME native DLLs 步骤把复制 dll 移到循环里,x64 + x86 都覆盖
仓库占位
- 仓库新增 0 字节 x86 占位 dll,让本地 mac/linux 构建也能 resolve resources
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
P1 review 已采纳:commit c52658b 把 x86 dll 也加入 bundle.resources + installer.nsh 用 SysWOW64\regsvr32 注册,让 inspect_windows_ime_registration() 两次 WOW64 校验都能通过。 |
PR Reviewer Guide 🔍(Review updated until commit 81fa80d)Here are some key observations to aid the review process:
|
|
Persistent review updated to latest commit c52658b |
NSIS installer 是 32-bit 进程,进程内的 $SYSDIR / $WINDIR\System32 都因
WOW64 文件系统重定向变成 $WINDIR\SysWOW64,跑的是 32-bit regsvr32 → x64 dll
被注册到 HKLM\Software\Wow6432Node\Classes\CLSID(KEY_WOW64_32KEY 视图)。
但 windows_ime_profile.rs 用 KEY_WOW64_64KEY 校验时只看 HKLM\Software\Classes
\CLSID,永远查不到 → 仍判 RegistrationBroken("OpenLess COM registration is
missing")。
修复:x64 改用 $WINDIR\Sysnative\regsvr32.exe — 这是 32-bit 进程访问真
64-bit System32 的专用 alias,写入会落在 KEY_WOW64_64KEY 视图。x86 保持
SysWOW64 不变(确实需要 32-bit regsvr32 写 Wow6432Node)。
|
再修一刀(commit 81fa80d):NSIS installer 是 32-bit 进程, |
|
Persistent review updated to latest commit 81fa80d |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81fa80da69
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| !macro NSIS_HOOK_POSTINSTALL | ||
| DetailPrint "Registering OpenLess TSF IME (x64) ..." | ||
| nsExec::ExecToLog '"$WINDIR\Sysnative\regsvr32.exe" /s "$INSTDIR\tsf-ime\x64\OpenLessIme.dll"' |
There was a problem hiding this comment.
Point regsvr32 at the resources directory
For NSIS installs, Tauri places bundle.resources under $INSTDIR\resources\... (the Windows installer docs' hook example accesses bundled resources from $INSTDIR\resources\), not directly under $INSTDIR. With the new map target tsf-ime/x64/OpenLessIme.dll, this hook looks for a file that is actually installed as $INSTDIR\resources\tsf-ime\x64\OpenLessIme.dll (and the x86 line has the same issue), so both regsvr32 calls fail and are ignored; NSIS/updater users still end up without the TSF COM registration the change is trying to add.
Useful? React with 👍 / 👎.
|
@codex 这次的 P1 我判定为误报,不修代码。证据:
所以 dll 实际安装到 |
|
To use Codex here, create an environment for this repo. |
main 上 Open-Less#268 (millionart/codex/register-windows-ime-nsis-installer) 与 Open-Less#279 (本人) 都修了 NSIS 注册 TSF DLL,merge Open-Less#279 时未手动解决冲突,导致: 1. tauri.conf.json 出现两个 windows.nsis block(line 92-95 和 105-108), serde_json 用最后写入的覆盖前面,结果 Open-Less#268 的 nsis/openless-ime-hooks.nsh 被丢弃,实际生效的是 Open-Less#279 的 installer.nsh。 2. Open-Less#279 的 bundle.resources 把 dll 多打一份到 $INSTDIR\tsf-ime\,与 Open-Less#268 PREINSTALL File 直接装到 $INSTDIR\windows-ime\ 并存。 3. installer.nsh 与 openless-ime-payload/ 残留为死代码。 Open-Less#268 方案更稳:x64 注册带 Sysnative + DisableX64FSRedirection 双保险,有 POSTUNINSTALL 清理 hook,有测试覆盖(4a7a1b6b/test、933e014a/test),且 不污染 MSI(不用 bundle.resources,避免 dll 重复)。 清理: - 删除 tauri.conf.json 重复 nsis block,保留 nsis/openless-ime-hooks.nsh - 删除 bundle.resources(Open-Less#268 不需要) - 删除死文件 installer.nsh - 删除死目录 openless-ime-payload/ release-tauri.yml 里"复制 dll 到 openless-ime-payload"步骤、build-mac.sh 与 Linux build 的 --config '{"bundle":{"resources":{}}}' override 暂留 — 没有 bundle.resources 后这些是 noop,不会破坏 build;当前 token 没有 workflow scope,等下一次有需求再清。
主要修复 ───────── - fix(windows): NSIS 安装包注册 OpenLess TSF DLL(含 32-bit COM 注册到 Wow6432Node + Sysnative 绕过 32-bit installer 的 WOW64 重定向); 改 perMachine 安装让 regsvr32 能写 HKLM。修「Windows 输入法后端:不可用」 自 1.2.15 起的长期 bug。 - fix(local-asr): 切走/删模型/手动释放时引擎真正归还 1+ GB RAM;下载稳定性 4 次指数退避 + Range 分块 + 取消正确传播;点击下载即崩(tokio::spawn → tauri::async_runtime)。 - fix(tauri): Rust crate tauri 锁 ~2.10,避开 npm 端 @tauri-apps/api 尚未发布 2.11 导致的跨 minor 版本检查 fail。 - fix(capsule): AudioBars 用 cubic-bezier 缓动 + 0.18s transition,圆点→ 长条形变在 60Hz audio level 高频更新下平滑混合,不再阶梯式跳变。 - fix(recorder): liveness watchdog + 全局超时;watchdog 从首次回调开始计时 避免慢启动误报(issue #238)。 - fix(windows): hotkey trigger leak、capsule 视觉异常、音量计稳定(多 PR)。 - fix(credentials): 凭据状态按 active provider 判断。 新功能 ───────── - feat(asr): 本地 Qwen3-ASR-Flash 全链路 — 模型注册表、HF/HF-Mirror 4 并发 分块下载、Settings → 模型设置页、Coordinator 第三分支接入。 - feat(i18n): 日本語 / 한국어 完整翻译(217 string × 2 语种)+ 5 locale 在语言名后加 Beta 标识。 - feat(translation): 输出语言扩展为日 / 韩,与翻译链路解耦。 - feat(recording): 录音时静音系统输出,多会话共享 mute guard。 - feat(i18n): 繁體中文 UI 完整 + 简繁脚本随 UI 切换同步。 - feat(settings): 合并设置内外两个「关于」(QQ 群 / 反馈 / 源码 / 隐私 全部并入弹窗的关于)+ 一键导出错误日志(plugin-dialog 选保存位置, 跨 macOS / Windows)。 工程 ───────── - chore(ci): release-tauri.yml + ci.yml checkout 拉 submodule,修 mac 端 qwen-asr build 缺源文件。 - chore(release-prep): 清理 #268/#279 双 NSIS 方案残留。 - chore(deps): 引入 tauri-plugin-dialog ~2 给前端 save dialog 用。
User description
Summary
1.2.20 发版候选,包含两个修复:
1. 修 Windows TSF 输入法显示「不可用」(NEW)
installer.nshPostInstall/PreUninstall hook 跑 regsvr32bundle.resources把 dll 拷到 `$INSTDIR\tsf-ime\OpenLessIme.dll`(避开 wxs 已用的 `windows-ime\x64\` 路径以免 MSI 冲突)2. 切走 / 删模型 / 手动释放时真正归还本地 ASR RAM
见 463a6d9 commit message。
Trade-off
Test plan
影响范围
PR Type
Bug fix, Enhancement
Description
Register TSF DLLs in NSIS
Package payloads under
tsf-imeCopy real DLLs during release
Skip placeholder DLLs on mac/Linux
Diagram Walkthrough
File Walkthrough
build-mac.sh
Override Tauri resources for mac buildsopenless-all/app/scripts/build-mac.sh
--config '{"bundle":{"resources":{}}}'totauri build..app.release-tauri.yml
Copy built DLLs into bundle payloads.github/workflows/release-tauri.yml
src-tauri/openless-ime-payload/{x64,x86}.bundle.resourcesto{}for Linux packaging.tauri.conf.json
Add TSF payload resources and NSIS hooksopenless-all/app/src-tauri/tauri.conf.json
tsf-ime/x64andtsf-ime/x86.perMachinefor HKLM access.installer.nshas the NSIS installer hook.installer.nsh
Register OpenLess TSF DLLs during installopenless-all/app/src-tauri/installer.nsh
regsvr32calls for x64 and x86 DLLs.