检查PowerShell是否处于调试模式

9

我如何在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

你可以通过传递一个开关给脚本来告诉它当前的状态(例如“调试”或“发布”),而不是猜测。你可以将开关的默认值设置为“调试”。 - rrirower
可能是 在 Cmdlet 中,如何检测 Debug 标志是否已设置? 的重复问题。 - Michael Freidgeim
3个回答

7
这是一个函数,可以轻松检查,还有一些选项可以改变行为。
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

4
在PowerShell中,“Debugged”可能意味着几件事情。1)程序正在调试器下运行,2)使用了-Debug标志或者$DebugPreferences不是SilentlyContinue,3)启用了PowerShell跟踪,4)使用Set-PSDebug切换了跟踪(一种不同于#3的跟踪方式)。如果您还没有选择其中之一,我建议您选择#2。它很简单(检查PSBoundVariables中是否有-Debug或者$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脚本的例子吗? - Ryan Gates
1
让我建议一下,更符合 SO 的精神(作为程序员解决特定编程问题的资源):如果需要,使用网络搜索查找示例并编写脚本。如果您在脚本方面遇到问题,请将其添加到原始帖子中并更新您的问题。 - Χpẘ

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接