【问题标题】:Check if in debug mode in PowerShell在 PowerShell 中检查是否处于调试模式
【发布时间】:2021-03-23 01:46:53
【问题描述】:

如果我的脚本在调试模式下运行,我如何检查 PowerShell?我目前正在安装 PowerShell 工具的 Visual Studio 2015 中进行调试。

脚本的一部分使用 Send-MailMessage 发送电子邮件。我想做类似下面的事情。

If (Debug)
{
    $messageProperties.To = "$env:username@company.com"
}
Else
{
    $messageProperties.To = "prodmailbox@company.com"
}

我知道在 C# 中我可以执行以下操作。我想知道在 PowerShell 中是如何处理的。

#if DEBUG
    // Debug code
#endif

【问题讨论】:

标签: powershell debugging


【解决方案1】:

这是一个让您轻松检查的功能;以及一些改变行为的选项。

function Test-Debug {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [switch]$IgnorePSBoundParameters
        ,
        [Parameter(Mandatory = $false)]
        [switch]$IgnoreDebugPreference
        ,
        [Parameter(Mandatory = $false)]
        [switch]$IgnorePSDebugContext
    )
    process {
        ((-not $IgnoreDebugPreference.IsPresent) -and ($DebugPreference -ne "SilentlyContinue")) -or
        ((-not $IgnorePSBoundParameters.IsPresent) -and $PSBoundParameters.Debug.IsPresent) -or
        ((-not $IgnorePSDebugContext.IsPresent) -and ($PSDebugContext))
    }
}

这里有一些代码来演示某些场景下的输出:

#region 'Test Functions'
function Test-InheritExplicit {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [switch]$IgnorePSBoundParameters
        ,
        [Parameter(Mandatory = $false)]
        [switch]$IgnoreDebugPreference
        ,
        [Parameter(Mandatory = $false)]
        [switch]$IgnorePSDebugContext
    )
    process {
        #if we weren't splatting all vars over, we could use this trick:
        #[switch]$DebugCopy = $PSBoundParameters.Debug
        #Test-Debug -Debug:$DebugCopy
        Test-Debug @PSBoundParameters
    }
}

function Test-InheritImplicit {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [switch]$IgnorePSBoundParameters
        ,
        [Parameter(Mandatory = $false)]
        [switch]$IgnoreDebugPreference
        ,
        [Parameter(Mandatory = $false)]
        [switch]$IgnorePSDebugContext
    )
    process {
        Test-Debug -IgnorePSBoundParameters:$IgnorePSBoundParameters -IgnorePSDebugContext:$IgnorePSDebugContext -IgnoreDebugPreference:$IgnoreDebugPreference
    }
}
#endregion 'Test Functions'

#region 'Test Cases'
[hashtable[]]$testCases = 0..15 | %{
    [hashtable]$new = @{}
    if ($_ -band 1) {$new.Debug = [switch]$true}
    if ($_ -band 2) {$new.IgnorePSBoundParameters = [switch]$true}            
    if ($_ -band 4) {$new.IgnoreDebugPreference = [switch]$true}
    if ($_ -band 8) {$new.IgnorePSDebugContext = [switch]$true}
    $new
}

[int]$t = 0
$testCases | %{
    [hashtable]$testCase = $_
    (New-Object -TypeName PSObject -Property @{
        TestId = ++$t
        Debug = [bool]$_.Debug
        IgnorePSBoundParameters = [bool]$_.IgnorePSBoundParameters
        IgnoreDebugPreference = [bool]$_.IgnoreDebugPreference
        IgnorePSDebugContext = [bool]$_.IgnorePSDebugContext
        TD = (Test-Debug @testCase)
        TIE = (Test-InheritExplicit @testCase)
        TII = (Test-InheritImplicit @testCase)
    })
} | Format-Table  TestId, Debug, IgnorePSBoundParameters, IgnoreDebugPreference, IgnorePSDebugContext, TD, TIE, TII -AutoSize

这是上面的输出:

TestId Debug IgnorePSBoundParameters IgnoreDebugPreference IgnorePSDebugContext    TD   TIE   TII
------ ----- ----------------------- --------------------- --------------------    --   ---   ---
     1 False                   False                 False                False False False False
     2  True                   False                 False                False  True  True  True
     3 False                    True                 False                False False False False
     4  True                    True                 False                False  True  True  True
     5 False                   False                  True                False False False False
     6  True                   False                  True                False  True  True False
     7 False                    True                  True                False False False False
     8  True                    True                  True                False False False False
     9 False                   False                 False                 True False False False
    10  True                   False                 False                 True  True  True  True
    11 False                    True                 False                 True False False False
    12  True                    True                 False                 True  True  True  True
    13 False                   False                  True                 True False False False
    14  True                   False                  True                 True  True  True False
    15 False                    True                  True                 True False False False
    16  True                    True                  True                 True False False False

【讨论】:

    【解决方案2】:

    PowerShell 中的“已调试”可能意味着几件事。 1) 程序在调试器下运行,2) cmdlet/函数通过-Debug 标志或$DebugPreferences 不是SilentlyContinue 3) PowerShell 跟踪已打开,4) Set-PSDebug 用于切换跟踪(a不同于 #3 的跟踪类型)。

    如果您还没有选择其中之一,我建议您选择 #2。这很简单(检查-Debug 是否在PSBoundVariables 中或$DebugPreferences 的值不是SilentlyContinue)。它支持Write-Debug cmdlet。一般而言,这是切换调试输出的 PowerShell 方式。

    如果你真的需要#1,那么正如this page 解释的那样,在其核心实现 PowerShell 调试器是处理两个事件(Debugger.BreakpointUpdatedDebugger.DebuggerStop),所以你需要看看是否有这些事件的处理程序事件。

    如果您需要 #4,您可能需要访问私有数据。唯一以 PSDebug 为名词的 PowerShell 3.0 命令是 Set-PSDebug,这意味着没有 cmdlet 可以返回 PSDebug 的状态。

    如果你需要#3,那么情况类似于#4。没有 cmdlet 可以返回所跟踪内容的信息。

    【讨论】:

    • 您能否在 PowerShell 脚本中为每个选项提供一个示例?
    • 让我建议这一点,更符合 SO 的精神(作为解决特定编程问题的程序员资源):如有必要,使用网络搜索查找示例,编写脚本。如果您对脚本有问题,请将其添加到 OP 并更新您的问题。
    【解决方案3】:

    具有向后兼容性的示例模板脚本(以及一些注释)

    # turn regular script into advanced script by adding the cmdletbinding attribute and its required param()
    [CmdletBinding()]
    Param()
    
    $DebugPreferenceWas = $DebugPreference
    
    # $debugPreference is default to "SilentlyContinue"
    # if -debug argument passed, we get "$DebugPreference=Inquire"
    if ($DebugPreference -ne "SilentlyContinue" -And $PSVersionTable.PSVersion.Major -lt 6) {
        # note: for backward compatibility set $DebugPreference='Continue'
        #       prior to PowerShell 6, we would have to answer a question for each Debug message, this change in v6
        Write-Output "Backward compatibility, update DebugPreference"
        $DebugPreference = 'Continue'
        Write-Output "DebugPreference was: $DebugPreferenceWas, changed to: $DebugPreference"
    }
    
    Write-Debug "this line will only print if -Debug was passed to the script"
    
    Write-Output "script ran, exiting"
    

    因此,就像我们进行检查一样,您可以执行以下操作:

    [CmdletBinding()]
    Param()
    
    # ... some code here creating variables or whatnot ...
    
    if ($DebugPreference -ne "SilentlyContinue") {
      # in debug
      $messageProperties.To = "$env:username@company.com"
    } else {
      # not debug
      $messageProperties.To = "prodmailbox@company.com"
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-02
      • 2011-11-24
      • 2018-01-28
      • 2018-08-21
      • 2020-03-04
      相关资源
      最近更新 更多