在Powershell脚本中跟踪输出的来源

时间:2018-11-22 04:04:13

标签: powershell debugging scripting output powershell-v3.0

是否可以跟踪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}
}

2 个答案:

答案 0 :(得分:0)

是,尝试这个。无论何时首次找到写语句,这都应该中断。

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

此命令在Sample.ps1脚本中以写开头的每个命令(例如Write-Host)上设置一个断点。欲了解更多 请参阅docs

答案 1 :(得分:0)

不幸的是

  • Set-PSBreakpoint -Command非常适合显式 cmdlet调用

    • 例如,在脚本Write-Output中对Write-Host./myscript.ps1的调用会导致通过先前的Set-PSBreakpoint -Command Write-* ./myscript.ps1调用而进入调试器),
  • 不能与隐式输出配合使用,该输出来自既不捕获也不重定向输出的语句(例如{{1 }},'foo'1 + 2)。

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

解决方法

  • 在调用脚本之前运行 = ,该脚本在产生输出之前先打印每个源代码行(如果有)。 Set-PSDebug -Trace 1提供了其他详细信息。

  • 使用以下技术,可以告诉您产生成功输出的第一行的数字,无论是隐式还是显式;请注意,但是,此时脚本执行被中止了

    -Trace 2
    • 脚本的成功输出通过管道传递到try { ./myscript.ps1 | Write-Error -EA Stop } catch { "$_"; $_.ScriptStackTrace } ,后者将输出(字符串化的版本)重定向到PowerShell的错误流,其中Write-Error-EA Stop的缩写)导致执行中止在将输出发送到错误流时;然后,-ErrorAction Stop块输出结果错误记录的字符串化版本(其本身就是原始输出的字符串化版本),然后是脚本调用堆栈跟踪,其第一行显示了该行的编号产生了输出。
    • 注意:如果脚本在第一次成功输出之前碰巧产生了 statement 终止错误,则该技术将不起作用。
  • 如果要在给定的行中检查脚本的运行时状态,请说catch

    • 15

    • 或者,在PSv5 +中,如果可以选择(临时)修改脚本,则在脚本中要插入调试器的位置进行Set-PSBreakpoint -Script ./myscript.ps1 -Line 15调用。

  • 使用 Visual Studio CodePowerShell extension 的调试功能来设置断点和/或逐步执行脚本逐条陈述。

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