在powershell中检查是否处于调试模式

时间:2016-02-17 15:32:58

标签: powershell debugging

如果我的脚本在调试模式下运行,如何检查powershell?我目前正在安装PowerShell Tools的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

3 个答案:

答案 0 :(得分:3)

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

如果你还没有选择其中一个,我建议你选择#2。这很简单(检查-DebugPSBoundVariables还是$DebugPreferences的值不是SilentlyContinue)。它支持Write-Debug cmdlet。一般而言,它是Powershell-toh切换调试输出的方法。

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

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

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

答案 1 :(得分:3)

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

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 :(得分:1)

具有向后兼容性的示例模板脚本(和一点注释)

# 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"
}