Powershell“Set-PSDebug -Trace 2”导致意外结果
Posted
技术标签:
【中文标题】Powershell“Set-PSDebug -Trace 2”导致意外结果【英文标题】:Powershell "Set-PSDebug -Trace 2" causes unexpected results 【发布时间】:2013-09-14 07:42:12 【问题描述】:我遇到了一个奇怪的问题,即在设置“Set-PSDebug -Trace 2”时出现不同的行为。
我将其追溯到一个未正确执行的 switch 语句,并且能够在 Powershell V3 上重现它,但不能在 Powershell V2 或 Powershell V1 上重现(按预期工作)
取如下简单函数:
function DoTest
$result = "Switch Case Not Executed"
$VendorName = "Microsoft"
switch ($VendorName)
"Microsoft" $result = "Switch Case Executed"
Write-host "Switch: $($VendorName) -> $result"
现在运行以下命令:
#Works as expected
Set-PSDebug -Off; DoTest;
#Doesn't work as expected
Set-PSDebug -Trace 2; DoTest;
带有 PSDebug Trace 的 PosH V3 上的结果
DEBUG: 3+ Set-PSDebug -Trace 2; >>>> DoTest;
DEBUG: 1+ function DoTest >>>>
DEBUG: ! CALL function 'DoTest'
DEBUG: 2+ >>>> $result = "Switch Case Not Executed"
DEBUG: ! SET $result = 'Switch Case Not Executed'.
DEBUG: 3+ >>>> $VendorName = "Microsoft"
DEBUG: ! SET $VendorName = 'Microsoft'.
DEBUG: ! SET $switch = 'Microsoft'.
DEBUG: 4+ switch ( >>>> $VendorName)
DEBUG: ! SET $switch = ''.
DEBUG: 9+ >>>> Write-host "Switch: $($VendorName) -> $result"
DEBUG: 9+ Write-host "Switch: $( >>>> $VendorName) -> $result"
Switch: Microsoft -> Switch Case Not Executed
DEBUG: 11+ >>>>
在 PoSH 版本 3 中,即使是调试跟踪也表明该值已设置,但似乎完全跳过了 switch 语句。我什至尝试了Set-StrictMode
,一切运行良好。只有当我启用 PSDebug 跟踪时。这种行为是有意的吗?
【问题讨论】:
【参考方案1】:经过详尽调查,这似乎是 Powershell 中的一个错误。 $switch
变量在调试模式下被破坏,最终成为某种数组枚举器,在一个空数组或类似的东西上。我建议在http://connect.microsoft.com 上提交问题
解决方法 1:
# Pro: No scoping differences between if statement blocks and function
# Con: big piles of If ... else if ... else if ... can get really annoying to code and maintain
# Con: Statements are limited to single execution, pipeline is lifted to function level instead of statement level
... same code as before but using an if instead of switch ...
if($VendorName = 'Microsoft') $result = "Switch Case Executed"
else $result = "FAIL!"
解决方法 2:
# Pro: Each script block is self-contained and has private scope
# Pro: "cases" can be added without modifying DoIt function, and even passed into the function
# Pro: "cases" can be used in a pipeline
# Con: Indirect script blocks can be difficult to understand at first
function DoTest
$result = "Switch Case Not Executed"
$VendorName = "Microsoft"
$SwitchHack = @
Microsoft = "Microsoft Case Executed"
Default = "Default Case Executed"
if($SwitchHack.Keys -contains $VendorName)
$result = $SwitchHack."$VendorName".InvokeReturnAsIs()
else
$result = $SwitchHack.Default.InvokeReturnAsIs()
'Switch: 0 -> 1' -f $VendorName, $result | Write-Host
Set-PSDebug -Trace 2
DoTest
因为我很无聊,所以我写了 Workaround 3,它只有 2 个,将 Switch 移到一个函数中
function Switch-Object
param(
[Parameter(Mandatory=$true)]
[String]$In,
[Parameter(Mandatory=$true)]
[hashtable]$Actions
)
try
$Actions."$In".InvokeReturnAsIs()
catch
throw "Unknown Action Label"
function DoTest
$result = "Switch Case Not Executed"
$VendorName = "Microsoft"
$VendorActions = @
Microsoft = "Microsoft Case Executed"
$result = Switch-Object -On:$VendorName -Actions:$VendorActions
'Switch: 0 -> 1' -f $VendorName, $result | Write-Host
Set-PSDebug -Trace 2
DoTest
【讨论】:
谢谢@Eris!我用Microsoft Connect 打开了一个错误 我们在使用Set-PSDebug -Trace 1
和 foreach 时遇到过类似的问题。如果我们执行foreach(var $item in $something)
,则不会发生迭代。与 $something | ForEach-Object
... 一起工作正常。我们使用跟踪来衡量自动化测试的代码覆盖率 - 现在在 PowerShell 3 下已经严重损坏......以上是关于Powershell“Set-PSDebug -Trace 2”导致意外结果的主要内容,如果未能解决你的问题,请参考以下文章
powershell PowerShell:启动PowerShell作为其他用户提升
powershell [提示输入powershell] #powershell #input #prompt