【问题标题】:Powershell "Set-PSDebug -Trace 2" causes unexpected resultsPowershell“Set-PSDebug -Trace 2”导致意外结果
【发布时间】: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 跟踪时。这种行为是有意的吗?

【问题讨论】:

    标签: powershell switch-statement script-debugging


    【解决方案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 下已经严重损坏......
    猜你喜欢
    • 2021-04-24
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多