【问题标题】:Tracing where output is coming from in a Powershell script在 Powershell 脚本中跟踪输出的来源
【发布时间】:2019-04-24 17:02:50
【问题描述】:

是否可以在 Powershell 脚本中跟踪输出(到控制台)的来源?我有一个向我输出信息的脚本,但我不确定哪一行正在输出。例如,是否可以使用 Set-PSBreakpoint 并告诉它在信息返回到控制台时中断?

干杯


我收到了数百个“False”在他们自己的线路上返回。 这是输出来自的代码部分:

    $ar = Function-which_returns_array_of_objects
    $gr = Function-which_returns_array_of_objects

    Write-Host "To begin with..."
    Write-Host "$($ar.count) assets"
    Write-Host "$($gr.count) goods"

    foreach($asset in $ar){
        if(!(Test-NoNA -string $asset.Serial)){continue}

        #See if the particular serial number exists in Goods Received
        $found = @()
        $gr | Where {$_.SerialNumber -eq $asset.serial} | %{
            $found += $_
            # and then mark the entry as one that has to be deleted from GR
            $_.Delete = "YES"
        }
        if($found.count -eq 1){
            #Serial Number has been found once in GR
            #We want to check its PN...
            if(Test-NoNA -string $found.PartNumber -and $found.PartNumber -ne $asset.Model){
                #add it to the asset if its good and not the same as the model number...
                $asset.PartNumber -eq $found.PartNumber
            }
        }elseif(!$found -or $found.count -eq 0){
            #No entries found in GR
            #Shouldn't be the case but doesn't actually do any damage as we'd be deleting the GR entry anyway
        }elseif($found.count -gt 1){
            #More than one match for the SN - probably means a SN like "N/A" has got through the earlier checks
            Write-Warning "More than one match for SN: '$($asset.serial)'"
        }else{
            #Default catcher
            Write-Warning "Unknown Error for SN: '$($asset.serial)'"
        }
    }

还有,这里是 Test-NoNA:

function Test-NoNA($string){
#check that the given string is not blank, N/A, ?, etc. Returns true if string is good
if($string -and $string -ne "" -and $string -ne "N/A" -and $string -ne "NA" -and $string -ne '?' -and $string -isnot [System.DBNull]){return $true}
}

【问题讨论】:

  • 请发布输出,以便我们可以大胆猜测您的哪一行仍然保密的代码触发了这些东西。当然,您可以尝试发布一些代码... [grin] 我知道可能无法发布整个脚本 - 但如果可以,请执行所以。也许到 Gist.GitHub?
  • 这条线$asset.PartNumber -eq $found.PartNumber 看起来是问题的一部分。您的评论使您似乎打算将-eq 设为=。 [咧嘴]
  • 啊,就是这样!这也解释了脚本的其他一些问题。
  • 酷!很高兴知道你把它修好了... [grin]

标签: powershell debugging scripting output powershell-3.0


【解决方案1】:

是的,试试这个。这应该在第一次找到写语句的地方中断。

  Set-PSBreakpoint -Script Sample.ps1 -Command "write*"

此命令在 Sample.ps1 脚本中以 write 开头的每个命令上设置断点,例如 Write-Host。更多 参考docs

【讨论】:

  • @Harihan 谢谢,但输出不是来自“Write-*”风格的命令——我认为它是从函数或运算符返回的。我追求的是在生成输出时捕获的东西,而不是在调用某些命令时捕获的东西。
  • 那么你应该发布一些示例代码以便更好地澄清。
  • 我已编辑问题以包含一些示例代码
【解决方案2】:

很遗憾,

  • Set-PSBreakpoint -Command显式 cmdlet 调用效果很好

    • 例如,在脚本./myscript.ps1 中调用Write-OutputWrite-Host 会导致在之前调用Set-PSBreakpoint -Command Write-* ./myscript.ps1 时闯入调试器),
  • 隐式输出一起工作,来自既不捕获也不重定向输出的语句(例如,'foo'、@987654332 @, Get-Date)。

在当前的特定情况下,$asset.PartNumber -eq $found.PartNumber 之类的语句导致了不需要的输出,这是由于 @987654321 诊断的 @987654321 诊断的 -eq 运算符(比较)与 = 运算符(赋值)混淆@。 -eq 产生输出(比较的布尔结果),而 = 不产生。

解决方法

  • 在调用您的脚本之前运行 Set-PSDebug -Trace 1,该脚本在输出之前打印每个源代码行(如果有)。 -Trace 2 提供更多详细信息。

  • 使用以下技术,该技术告诉您产生成功输出的每个语句的位置和源代码,无论是隐式还是显式:

    ./myscript.ps1 | % { Write-Verbose -vb "Output from $(($entry=(Get-PsCallStack)[1]).Location): $($entry.Position.Text)"; $_ }
    
    • 脚本的成功输出通过ForEach-Object (%) 逐个对象处理,生成详细消息报告位置(脚本路径和行号)以及原始语句的源代码(通过@获得987654323@),然后通过手头的对象 ($_)。
  • 如果您想检查给定行上脚本的运行时状态,请说15

    • Set-PSBreakpoint -Script ./myscript.ps1 -Line 15

    • 或者,在 PSv5+ 中,如果可以选择(临时)修改脚本,请在脚本中您想要进入调试器的位置调用 Wait-Debugger

  • 使用 Visual Studio Code 的调试功能和 PowerShell extension设置断点和/或逐句执行脚本

    • 或者,直接在 PowerShell 窗口中使用 Set-PSDebug -Step 进行等效操作。

【讨论】:

    猜你喜欢
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多