Rom*_*man 9 powershell alias mkdir
这是令人难以置信的事情.这是test.ps1文件中的PowerShell代码段:
Set-StrictMode -Version 2
mkdir c:\tmp\1 # same with 'md c:\tmp\1'
Run Code Online (Sandbox Code Playgroud)
开始cmd.exe,使用test.ps1脚本导航到文件夹并运行它:
c:\tmp>powershell ".\test.ps1"
Run Code Online (Sandbox Code Playgroud)
这会产生以下错误:
The variable '$_' cannot be retrieved because it has not been set.
At line:50 char:38
+ $steppablePipeline.Process($_ <<<< )
+ CategoryInfo : InvalidOperation: (_:Token) [], ParentContainsEr
rorRecordException
+ FullyQualifiedErrorId : VariableIsUndefined
Run Code Online (Sandbox Code Playgroud)
为什么?
它从PowerShell控制台启动但不是cmd.exe时有效.我在更大的脚本中发现了这个bug.这是一个WTF时刻.
这个简单的脚本有什么问题?
Art*_*gus 14
尽管已经找到了解决方法,但我认为人们可能会对解释感兴趣.
至于为什么它在shell与cmd.exe中的行为不同,请参阅Powershell 2.0 - 从ISE运行命令行调用脚本
如参考文献中所述,以下两个命令之间存在差异:
powershell ".\test.ps1"
powershell -File ".\test.ps1"
Run Code Online (Sandbox Code Playgroud)
使用第一种语法时,它似乎与范围混乱,导致Set-StrictMode命令修改全局范围内定义的函数的严格模式.
这会在mkdir函数的定义中触发错误(或者可能是错误的假设).
该函数使用GetSteppablePipeline方法来代理New-Item cmdlet的管道.然而,作者忽略了这样一个事实,即即使管道中没有任何东西,PROCESS部分仍然被执行.因此,当到达PROCESS部分时,未定义$ _自动变量.如果启用了严格模式,则会发生异常.
微软解决这个问题的一种方法是更换以下行:
$steppablePipeline.Process($_)
Run Code Online (Sandbox Code Playgroud)
以下内容:
if (test-path Variable:Local:_) {
$steppablePipeline.Process($_)
}
Run Code Online (Sandbox Code Playgroud)
我承认这可能不是修复它的最佳方法,但开销可以忽略不计.另一种选择是以某种方式测试BEGIN部分中的管道是否为空,然后将$ _设置为$ null.
无论哪种方式,如果您使用"powershell.exe -File filename"语法运行脚本,那么您不必担心它.
| 归档时间: |
|
| 查看次数: |
4718 次 |
| 最近记录: |