PowerShell 是 Windows 下强大的自动化和脚本工具,但在实际使用中,从初学者到老手都会遇到各种令人头疼的错误。本文整理了我日常使用中碰到的最常见的七类 PowerShell 脚本错误,附带错误信息示例和清晰的解决方案。
1. 执行策略限制(ExecutionPolicy)
错误信息
.\myscript.ps1 : 无法加载文件 .\myscript.ps1,因为在此系统上禁止运行脚本。
有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
所在位置 行:1 字符: 1
+ .\myscript.ps1
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess原因
PowerShell 默认执行策略为 Restricted,禁止运行任何 .ps1 脚本文件。这是安全设计,防止恶意脚本自动执行。
查看当前策略
Get-ExecutionPolicy
# 输出通常是 Restricted解决方法
| 方法 | 命令 | 适用场景 |
|---|---|---|
| 临时绕过(推荐) | powershell -ExecutionPolicy Bypass -File .\script.ps1 |
一次性执行,不改系统配置 |
| 当前用户放宽 | Set-ExecutionPolicy RemoteSigned -Scope CurrentUser |
允许本地脚本、远程脚本需签名 |
| 全局放宽 | Set-ExecutionPolicy RemoteSigned -Scope LocalMachine(需管理员) |
开发机常用 |
| 完全放开(不推荐) | Set-ExecutionPolicy Unrestricted |
仅限隔离环境 |
建议:日常使用
RemoteSigned即可——它允许本地编写的脚本直接运行,从网络下载的脚本需要数字签名或手动解除锁定。
解除单个文件的锁定
如果脚本是从网络下载的,即使设置了 RemoteSigned,Windows 也会标记该文件来自网络:
Unblock-File -Path .\downloaded-script.ps12. 路径中有空格未加引号
错误信息
C:\Program : 无法将"C:\Program"项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
所在位置 行:1 字符: 1
+ C:\Program Files\MyTool\script.ps1
+ ~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Program:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException原因
PowerShell 的路径解析机制:空格被视为参数分隔符,C:\Program Files\... 会被解析成尝试调用 C:\Program 命令并传入 Files\MyTool\script.ps1 作为参数。
解决方法
# ❌ 错误写法
C:\Program Files\MyTool\script.ps1
# ✅ 正确写法之一:使用调用运算符 &
& "C:\Program Files\MyTool\script.ps1"
# ✅ 正确写法之二:使用引号包裹并调用
. "C:\Program Files\MyTool\script.ps1"
# ✅ 正确写法之三:使用 Invoke-Expression(注意安全风险)
Invoke-Expression "C:\Program Files\MyTool\script.ps1"
# ✅ 正确写法之四:Tab 补全(PowerShell 会自动加引号和 &)
# 输入 C:\Prog 然后按 Tab| 写法 | 优点 | 注意 |
|---|---|---|
& "path" |
显式调用,最推荐 | 会创建子作用域 |
. "path" |
在当前作用域执行(dot-sourcing) | 脚本变量会污染当前会话 |
Invoke-Expression |
灵活 | 存在注入风险,不推荐 |
3. 编码问题:中文乱码
错误信息
# 现象:脚本中的中文字符显示为乱码或导致语法错误
所在位置 行:5 字符: 15
+ Write-Host "鏂囦欢宸插垹闄? # 原本应该是"文件已删除"
字符串缺少终止符: "。
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString原因
- Windows PowerShell 5.1:默认使用 ANSI 编码(中文系统为 GBK/CP936),如果你用 VS Code 保存为 UTF-8,脚本中的中文会变成乱码。
- PowerShell 7 (pwsh):默认使用 UTF-8,但如果文件是 UTF-8 with BOM,有时也会出问题。
| PowerShell 版本 | 默认脚本编码 | 建议保存格式 |
|---|---|---|
| Windows PowerShell 5.1 ISE | UTF-16 LE (Unicode) | UTF-8 with BOM |
| Windows PowerShell 5.1 控制台 | ANSI (GBK) | UTF-8 with BOM |
| PowerShell 7 (pwsh.exe) | UTF-8 | UTF-8 (有无 BOM 均可) |
解决方法
方案一:保存时选择正确编码(VS Code)
# VS Code 底部状态栏点击编码 → 选择"通过编码保存" →
# 对于 PS 5.1:选择 "UTF-8 with BOM"
# 对于 PS 7: 选择 "UTF-8"方案二:在脚本顶部显式指定编码
如果必须使用 UTF-8 脚本在 PS 5.1 中运行:
# 在 PowerShell 控制台中:
powershell -ExecutionPolicy Bypass -File .\script.ps1
# PS 5.1 中可以通过读取 UTF-8 文件来执行:
$script = Get-Content -Path ".\script.ps1" -Encoding UTF8 -Raw
Invoke-Expression $script方案三:统一升级到 PowerShell 7
# 安装 PowerShell 7(推荐)
winget install Microsoft.PowerShell
# 之后用 pwsh.exe 代替 powershell.exe 执行脚本4. 模块未安装或导入失败
错误信息
Import-Module : 未加载指定的模块"Az",因为在任何模块目录中都没有找到有效模块文件。
所在位置 行:1 字符: 1
+ Import-Module Az
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (Az:String) [Import-Module], FileNotFoundException
+ FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand常见场景和解决
| 场景 | 错误特征 | 解决方法 |
|---|---|---|
| 模块未安装 | ModuleNotFound |
Install-Module -Name Az -Force |
| 模块版本不兼容 | Version mismatch |
Install-Module -Name Az -RequiredVersion 10.0.0 |
| PS 版本不支持 | 模块要求 PS 7+ | 升级到 pwsh 或找旧版模块 |
路径不在 $env:PSModulePath |
同上 ModuleNotFound |
手动 Import-Module "D:\MyModules\MyModule" |
| 需要管理员权限安装 | Access denied |
以管理员身份运行 Install-Module 或加 -Scope CurrentUser |
诊断命令
# 查看已安装的模块
Get-Module -ListAvailable
# 查看模块安装路径
$env:PSModulePath -split ';'
# 查看模块是否在仓库中
Find-Module -Name Az
# 查看模块依赖
Find-Module -Name Az | Select-Object -ExpandProperty Dependencies离线环境安装
# 在联网机器上下载模块(保存为 .nupkg)
Save-Module -Name Az -Path "D:\OfflineModules"
# 复制到离线机器后安装
Install-Module -Name Az -Repository "D:\OfflineModules"5. 权限不足(需要管理员)
错误信息
New-Item : 拒绝访问路径"C:\Program Files\MyApp\config.json"。
所在位置 行:1 字符: 1
+ New-Item -Path "C:\Program Files\MyApp\config.json"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Program Files\MyApp\config.json:String) [New-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.NewItemCommand检测是否需要管理员
# 检查当前是否以管理员身份运行
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
if (-not $isAdmin) {
Write-Host "请以管理员身份重新运行此脚本" -ForegroundColor Red
}脚本中自动提升权限
# 检测并自动以管理员身份重新启动
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
$arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`""
Start-Process powershell.exe -Verb RunAs -ArgumentList $arguments
exit
}
# 之后的代码将以管理员权限运行
Write-Host "当前以管理员身份运行" -ForegroundColor Green常见需要管理员的操作
| 操作 | 是否需要管理员 |
|---|---|
修改 C:\Program Files\ 下的文件 |
✅ 需要 |
修改 C:\Windows\System32\ 下的文件 |
✅ 需要 |
| 安装全局 PowerShell 模块 | ✅ 需要(-Scope CurrentUser 可绕过) |
| 修改系统环境变量 | ✅ 需要 |
| 启动/停止 Windows 服务 | ✅ 需要 |
修改注册表 HKLM |
✅ 需要 |
| 用户目录下的操作 | ❌ 不需要 |
修改注册表 HKCU |
❌ 不需要 |
| 读取文件/服务状态 | ❌ 通常不需要 |
6. 脚本签名问题
错误信息
.\script.ps1 : 文件 .\script.ps1 未经数字签名。无法在当前系统上运行该脚本。
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess原因
当执行策略设置为 AllSigned 时,所有脚本都必须经过受信任的发布者签名。
解决方法
| 方法 | 命令 | 适用场景 |
|---|---|---|
| 调整执行策略 | Set-ExecutionPolicy RemoteSigned -Scope CurrentUser |
仅签远程脚本,本地不签 |
| 自签名证书 | 见下方代码 | 企业内部部署 |
| 解除阻止 | Unblock-File .\script.ps1 |
文件来自可信来源 |
| 临时绕过 | powershell -ExecutionPolicy Bypass -File .\script.ps1 |
单次执行 |
创建自签名证书并签名脚本
# 1. 创建自签名证书
$cert = New-SelfSignedCertificate -Subject "CN=MyPowerShellScripts" `
-Type CodeSigningCert `
-CertStoreLocation "Cert:\CurrentUser\My"
# 2. 签名脚本
Set-AuthenticodeSignature -FilePath ".\script.ps1" -Certificate $cert
# 3. 验证签名
Get-AuthenticodeSignature -FilePath ".\script.ps1"
# Status 应为 Valid
# 4.(可选)将证书导出给其他机器信任
Export-Certificate -Cert $cert -FilePath ".\MyPSRoot.cer"7. 兼容性问题(PS 5.1 vs PS 7)
常见不兼容现象
| 特性 | PowerShell 5.1 | PowerShell 7 |
|---|---|---|
| 默认编码 | Windows-1252 / GBK | UTF-8 |
&& / \|\| 运算符 |
❌ 不支持 | ✅ 支持 |
三元运算符 a ? b : c |
❌ 不支持 | ✅ 支持 |
ForEach-Object -Parallel |
❌ 不支持 | ✅ 支持 |
ConvertFrom-Json 深度限制 |
100 层 | 1024 层 |
| WPF/WinForms GUI | ✅ 原生支持 | ⚠️ 需额外配置 |
Invoke-WebRequest |
IE 引擎解析 DOM | 基础解析 |
Out-GridView |
✅ 支持 | ⚠️ 需安装模块 |
| COM 对象 | ✅ 原生支持 | ⚠️ 部分支持 |
错误示例:PS 7 特有语法在 PS 5.1 中报错
# 这段代码在 PS 7 中没问题,在 PS 5.1 中会报错
$result = Test-Path "C:\Windows" ? "存在" : "不存在"
# PS 5.1 错误:Unexpected token '?' in expression or statement.检查当前版本
$PSVersionTable.PSVersion
# 输出示例:Major Minor Build Revision
# ----- ----- ----- --------
# 5 1 19041 4291多版本兼容写法
# 条件判断替代三元运算符(兼容 PS 5.1)
if (Test-Path "C:\Windows") {
$result = "存在"
} else {
$result = "不存在"
}
# 使用 #requires 限制脚本运行环境
#requires -Version 7.0
# 如果版本不满足,脚本会直接中止并提示用户
# 动态检测版本并分支
if ($PSVersionTable.PSVersion.Major -ge 7) {
# PS 7+ 代码路径
$null = Test-Path "C:\Windows" ? $true : $false
} else {
# PS 5.1 兼容代码
$null = if (Test-Path "C:\Windows") { $true } else { $false }
}快速排查清单
遇到 PowerShell 脚本报错时,按以下顺序排查:
- 阅读错误信息的第一行和最后一行——通常已经说明了根本原因
$Error[0] \| Format-List -Force—— 查看完整错误详情$Error[0].Exception.InnerException—— 查看内部异常- 检查执行策略:
Get-ExecutionPolicy - 检查 PowerShell 版本:
$PSVersionTable - 检查路径和文件是否存在:
Test-Path .\script.ps1 - 检查是否以管理员身份运行(如果涉及系统级操作)
- 检查文件编码:
Get-Content .\script.ps1 -Encoding UTF8
熟练掌握这七类错误及其解决方案,可以帮你节省大量排查时间。建议将本文加入收藏,遇到问题时按图索骥。如果你有更多实战中的 PowerShell 错误案例,欢迎在评论区分享!