PowerShell 5.1参数块带必选参数时$PSCommandPath为何失效?
PowerShell 5.1必选参数导致param默认值中$PSCommandPath为空的原因及解决
问题重现
脚本代码
param ( [Parameter(Mandatory)][string]$DummyOU, # 存放虚拟设备的OU [Parameter(Mandatory)][string]$CertTemplate, # 给Intune设备颁发证书用的CA证书模板短名称 [string]$logfile = "$([System.IO.Path]::GetFileNameWithoutExtension("$($PSCommandPath | Split-Path -Leaf)"))-log.csv" ) "$($PSCommandPath | Split-Path -Leaf)" | Out-File C:\Automation\test.txt "$([System.IO.Path]::GetFileNameWithoutExtension("$($PSCommandPath | Split-Path -Leaf)"))-log.csv" | Out-File C:\Automation\test.txt -Append "$logfile" | Out-File C:\Automation\test.txt -Append exit 0
执行命令
powershell.exe -ExecutionPolicy Bypass -File .\map-intune-certs.ps1 -DummyOU "Test" -CertTemplate "Test2"
执行结果(test.txt内容)
map-intune-certs.ps1 map-intune-certs-log.csv -log.csv
异常现象
$logfile变量值仅为-log.csv,而非预期的map-intune-certs-log.csv- 移除param块中的必选参数后,问题消失
- 仅PowerShell 5.1.22621.3880版本出现,PowerShell 7.4.3无此问题
原因分析
这是PowerShell 5.1的初始化顺序bug:
- 当param块中存在必选参数时,PowerShell会优先处理必选参数的输入解析流程(包括命令行参数解析或等待用户输入),此时param块内的参数默认值表达式会在
$PSCommandPath等自动变量完成初始化之前执行,导致$PSCommandPath取值为空 - 没有必选参数时,PowerShell会直接执行param块的默认值表达式,此时
$PSCommandPath已经完成初始化,能正常获取脚本文件名 - PowerShell 7+版本已经修复了这个自动变量初始化顺序的问题,所以不会出现该异常
解决方法
将默认值的赋值逻辑移至param块之后,避开自动变量未初始化的阶段:
param ( [Parameter(Mandatory)][string]$DummyOU, [Parameter(Mandatory)][string]$CertTemplate, [string]$logfile ) # 后续设置默认值 if (-not $logfile) { $scriptBaseName = [System.IO.Path]::GetFileNameWithoutExtension((Split-Path -Path $PSCommandPath -Leaf)) $logfile = "$scriptBaseName-log.csv" } # 原有逻辑保留 "$($PSCommandPath | Split-Path -Leaf)" | Out-File C:\Automation\test.txt "$([System.IO.Path]::GetFileNameWithoutExtension("$($PSCommandPath | Split-Path -Leaf)"))-log.csv" | Out-File C:\Automation\test.txt -Append "$logfile" | Out-File C:\Automation\test.txt -Append exit 0
内容的提问来源于stack exchange,提问作者Appleoddity
相关产品推荐
相关产品推荐

