PowerShell类方法中Get-ChildItem未抛出预期的找不到路径错误
问题:PowerShell类方法中Get-ChildItem未抛出预期路径错误
环境信息
- 平台:Windows 11(PowerShell 7.3.6)、WSL2(PowerShell 7.3.5)
- 异常差异:本地环境中类的独立方法内执行
Get-ChildItem未抛出路径不存在错误,但构造函数内执行会抛出;Ubuntu-Latest的CI/CD环境中两种写法均正常抛出错误
复现步骤
- 在
${Home}/test/目录下创建两个脚本文件,目录内无其他内容:test_in_method.ps1test_out_of_method.ps1
脚本内容
test_in_method.ps1
# PowerShell 7.3.6 on Windows Or Linux # test_in_method.ps1 class FormattedFileSystemPath { FormattedFileSystemPath([string] $Path) { $link_target = $this.PreProcess() } [string] PreProcess(){ Write-Verbose "PWD is:$PWD" -Verbose return (Get-ChildItem 'usr'| Where-Object Name -eq 'sbin') } } Write-Verbose ([FormattedFileSystemPath]::new('???')) -Verbose
test_out_of_method.ps1
# PowerShell 7.3.6 on Windows Or Linux # test_out_of_method.ps1 class FormattedFileSystemPath { FormattedFileSystemPath([string] $Path) { Write-Verbose "PWD is:$PWD" -Verbose $link_target = (Get-ChildItem 'usr'| Where-Object Name -eq 'sbin') } } Write-Verbose ([FormattedFileSystemPath]::new('???')) -Verbose
测试结果
执行test_in_method.ps1
pwsh cd "${Home}/test/" ./test_in_method.ps1
输出:
VERBOSE: PWD is:C:\Users\User\test VERBOSE: FormattedFileSystemPath
执行test_out_of_method.ps1
pwsh cd "${Home}/test/" ./test_out_of_method.ps1
输出:
VERBOSE: PWD is:C:\Users\User\test Get-ChildItem: C:\Users\User\test\test_out_of_method.ps1:7 Line | 7 | $link_target = (Get-ChildItem 'usr'| Where-Object Name -eq 's … | ~~~~~~~~~~~~~~~~~~~ | Cannot find path 'C:\Users\User\test\usr' because it does not exist. VERBOSE: FormattedFileSystemPath
预期与实际行为
- 预期:两个脚本均抛出
Cannot find path错误 - 实际:仅
test_out_of_method.ps1抛出错误,test_in_method.ps1无报错
原因分析
这是PowerShell 7.3.x版本的已知bug:类的非构造函数方法中,命令抛出的非终止错误会被静默吞噬,不会向外暴露。
Get-ChildItem找不到路径时默认抛出的是非终止错误,在类的独立方法(如PreProcess)中这类错误无法传递到方法外部,导致脚本继续执行;但构造函数对错误的处理逻辑不同,非终止错误会正常抛出。而CI/CD环境使用的PowerShell版本已修复该bug,因此两种场景都能正常报错。
解决方法
1. 强制转换为终止错误
在Get-ChildItem中添加-ErrorAction Stop参数,确保错误终止执行并向外抛出:
[string] PreProcess(){ Write-Verbose "PWD is:$PWD" -Verbose return (Get-ChildItem 'usr' -ErrorAction Stop | Where-Object Name -eq 'sbin') }
2. 显式捕获并重新抛出
在方法内捕获错误,手动抛出终止错误:
[string] PreProcess(){ Write-Verbose "PWD is:$PWD" -Verbose try { return (Get-ChildItem 'usr' | Where-Object Name -eq 'sbin') } catch { throw $_ } }
3. 升级PowerShell版本
该bug在PowerShell 7.4及以上版本中已被修复,升级到最新稳定版可彻底解决问题。
内容的提问来源于stack exchange,提问作者Little Train
相关产品推荐
相关产品推荐

