你是不是也遇到过这个场景:在 Windows 上装完 Node.js,打开 PowerShell,敲下 npm -v,版本号没等到,先看到一大段红色报错:
powershell复制npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https://go.microsoft.com/fwlink/?LinkId=135170 中的 about_Execution_Policies。
所在位置 行:1 字符: 1
+ npm -v
+ ~~~
+ CategoryInfo : SecurityError: 可能试图运行脚本。
+ FullyQualifiedErrorId : UnauthorizedAccess
很多人的第一反应是 Node.js 没装好,于是卸载重装、改环境变量、去系统里翻文件,折腾半天问题毫无变化。实际上,这不是 npm 安装失败,也不是 PATH 配置有问题,而是 PowerShell 的“脚本运行权限错误”拦住了 npm 的 .ps1 包装脚本。这篇文章我会把这个问题的原理、排查步骤、解决方案和后续踩坑全部展开讲一遍,适合刚在 Windows 上配置 Node 环境、对 PowerShell 执行策略不熟的开发者参考。你不需要背命令,但我会尽量让你理解每条命令背后的理由,避免以后靠“瞎试”碰运气。
1. Node 安装过后,PowerShell 为什么会去执行 npm.ps1
1.1 一个 npm 命令,实际上对应了三种可执行形态
打开 Node.js 的安装目录,比如 C:\Program Files\nodejs\,你会看到三个和 npm 相关的文件:
npm:没有扩展名的 Shell 脚本,主要给 Git Bash、WSL、Unix-like 环境用的。npm.cmd:给 cmd.exe 和 Windows 批处理环境用的命令脚本。npm.ps1:给 PowerShell 用的包装脚本,内部会调用 Node.js 去执行npm-cli.js。
既然 Node.js 安装器已经把这三个文件都准备好了,为什么 PowerShell 不用 npm.cmd,偏偏去加载 npm.ps1?
这里要理解 PowerShell 的命令解析方式。你在 PowerShell 里输入 npm,它会优先在内存里找别名、函数、Cmdlet,找不到再去 PATH 环境变量对应的目录里找“可以被它调用的可执行文件”。和 cmd.exe 不同,PowerShell 会把 .ps1 脚本也当作一种可调用命令的来源,于是它能在 PATH 里同时看到 npm.cmd 和 npm.ps1。在不同操作系统和不同 PATH 顺序下,最终命中的对象不一定完全相同,但很多 Windows 环境中 PowerShell 会命中 npm.ps1。一旦命中 .ps1,执行策略就会介入了。
| 文件 | 由谁解释执行 | 使用场景 | 是否受 PowerShell 执行策略限制 |
|---|---|---|---|
npm |
sh / bash | Git Bash、WSL、类 Unix 环境 | 否 |
npm.cmd |
cmd.exe | cmd、批处理、传统命令行 | 否 |
npm.ps1 |
PowerShell | Windows PowerShell 5.1、PowerShell 7 | 是 |
1.2 PowerShell 不会把 .cmd 和 .ps1 当作一回事
很多在 cmd 下安装过 Node.js 的朋友会疑惑:我明明在 cmd 里执行 npm -v 是好的,怎么到 PowerShell 里就报错了?
原因就是 cmd.exe 和 PowerShell 对命令脚本的处理机制不同。cmd 会选择 npm.cmd 或者直接按批处理逻辑去执行包装命令,而 cmd/bat 文件不受 PowerShell ExecutionPolicy 限制。PowerShell 则不一样,它会把自己能识别的 .ps1 脚本纳入命令查找范围,而 .ps1 文件属于“脚本”,必须被 PowerShell 执行策略“审一遍”。当执行策略处于默认的 Restricted 状态时,任何 .ps1 脚本都不允许运行,于是你在 PowerShell 里敲 npm,系统刚找到 npm.ps1,还没执行就被拦下。
所以问题的核心很明确:不是 npm 本身出了故障,是 PowerShell 禁止运行 .ps1 这个“载体”。你从网上下载 Node.js 安装包、用安装器写入 PATH、这些都是正常的,真正卡住你的是脚本执行权限。
