前言
在 Windows 上管理 Node.js 版本,nvm-windows 几乎是唯一选择。但它只有命令行,每次切版本都要敲命令,而且因为涉及到 C:\Program Files\nodejs 的符号链接,每次启动都必须以管理员身份运行,UAC 弹窗烦不胜烦。
所以我用 PySide6 + pyside6-fluent-widgets 写了一个图形化界面,名字叫 nvmp。本来只是想给 nvm 套个皮,结果越写越上头,顺手把虚拟列表、异步操作、零 UAC 启动全做进去了。
效果预览
界面是 Fluent Design 风格,自动跟随系统深色/浅色主题。顶部显示当前 Node 版本和已安装数量,两个标签页分别展示已安装版本和可下载版本,右侧搜索框可以实时过滤。
核心特性
- 虚拟列表:可用版本有 800 多个,一次性渲染所有 DOM 会卡成 PPT。nvmp 用了虚拟化方案,只渲染视口内的行,滚动非常丝滑。
- 异步操作:安装、卸载、切换版本都是异步执行的,进度直接打在界面上,窗口永远不会卡死。
- 一键搜索:输入关键字实时过滤版本号,找 LTS 版本很方便。
- 零 UAC 启动:安装时只弹一次 UAC,之后从开始菜单或桌面启动再也不用弹窗。这个后面会详细讲实现原理。
零 UAC 是怎么做到的?
这是我觉得最值得分享的一个技术点。
nvm-windows 需要管理员权限的本质原因是它要操作 C:\Program Files\nodejs 目录和创建符号链接。所以 nvmp 本身也必须以管理员身份运行,否则调不动 nvm。
常规做法有三种:
- 每次启动都右键"以管理员身份运行"——最烦,pass。
- 给可执行文件加
requireAdministratormanifest——双击自动提权,但每次都会弹 UAC。 - 用计划任务(Scheduled Task)预授权——安装时以管理员身份注册一个最高权限计划任务,之后启动时通过
schtasks /Run触发该任务,Windows 直接以管理员身份启动进程,不再弹 UAC。
nvmp 选了方案 3,具体流程如下:
- 安装阶段:Inno Setup 安装器请求一次管理员权限,然后通过 PowerShell 的
Register-ScheduledTask注册一个名为nvmp的计划任务,设置RunLevel=Highest,并且不给它设置任何触发器(这样它不会自动运行)。 - 启动阶段:开始菜单和桌面的快捷方式并不直接指向
nvmp.exe,而是指向一个 VBS 脚本nvmp_launcher.vbs。这个脚本隐藏地调用schtasks /Run /TN nvmp,Windows 直接拉起预授权的高权限任务,nvmp 以管理员身份启动,全程无感。 - 卸载阶段:Inno Setup 的
[UninstallRun]自动执行schtasks /Delete,清理计划任务。
这样用户只要忍受一次安装时的 UAC,后续所有启动都是静默的。
技术栈
| 层 | 技术 |
|---|---|
| 语言 | Python 3.13 |
| GUI 框架 | PySide6 6.11 |
| 组件库 | pyside6-fluent-widgets 1.11 |
| 打包 | PyInstaller (onedir + windowed) |
| 安装器 | Inno Setup 6 |
| 依赖管理 | uv |
Fluent Widgets 这套组件库质感确实不错,配合 PySide6 的 QUiLoader 可以在 Qt Designer 里把 .ui 布局文件画好,运行时直接加载,开发和调整界面都很方便。
快速开始
普通用户
直接下载 release/nvmp-0.1.0-setup.exe 安装即可。安装完成后从开始菜单或桌面启动,享受零 UAC。
开发者
git clone https://gitee.com/pancilandtao/nvmp.git
cd nvmp
uv sync
uv run python main.py
打包安装器:
uv run python build_installer.py
输出在 dist/installer/nvmp-0.1.0-setup.exe。
写在最后
这个小工具本质上就是对 nvm-windows 的封装,没有特别高深的技术,但在细节上做了一点优化:虚拟列表解决大列表卡顿、异步操作避免 UI 卡死、计划任务解决 UAC 烦扰。如果你也在 Windows 上用 nvm,欢迎试试,提 Issue 或者 PR 都可以。
如果对你有帮助,欢迎点个 Star。