Powershell“Set-PSDebug -Trace 2"导致意想不到的结果 [英] Powershell "Set-PSDebug -Trace 2" causes unexpected results

查看:55
本文介绍了Powershell“Set-PSDebug -Trace 2"导致意想不到的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个奇怪的问题,在设置Set-PSDebug -Trace 2"时出现不同的行为.

I'm having a weird problem where I get different behavior when setting "Set-PSDebug -Trace 2".

我将其追溯到未正确执行的 switch 语句,并且能够在 Powershell V3 上重现它,但在 Powershell V2 或 Powershell V1 上无法重现(按预期工作)

I traced it down to a switch statement not executing properly and was able to reproduce it on Powershell V3 but not on Powershell V2 or Powershell V1 (works as expected)

采用以下简单函数:

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 上的结果

Results on PosH V3 with PSDebug Trace

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 跟踪时.这是有意为之吗?

In PoSH version 3, even the debug tracing indicates that the value is set, but it seems to skip the switch statement entirely. I even tried the Set-StrictMode and everything runs fine. It's only when I enable PSDebug tracing. Is this behavior intended?

推荐答案

经过详尽调查,这似乎是 Powershell 中的一个错误.$switch 变量在调试模式下被破坏,最终成为某种数组枚举器,在一个空数组或类似的东西上.我建议在 http://connect.microsoft.com

After exhaustive investigation, it appears to be a bug in Powershell. The $switch variable is getting clobbered in debug mode, and ends up being some sort of array enumerator, on an empty array or something silly like that. I recommend filing an issue on 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

因为无聊,我写了解决方法 3,它只是将 Switch 移到一个函数的 2

And because I was bored, I wrote Workaround 3 which is just 2 with the Switch moved to a function

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

这篇关于Powershell“Set-PSDebug -Trace 2"导致意想不到的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆