Reputation: 4539
How can I check in PowerShell if my script is running in debug mode? I am currently debugging in Visual Studio 2015 with PowerShell Tools installed.
A portion of the script sends an e-mail using Send-MailMessage. I would like to do something similar to below.
If (Debug)
{
$messageProperties.To = "$env:[email protected]"
}
Else
{
$messageProperties.To = "[email protected]"
}
I know in C# that I can do something like the below. I would like to know how this is handled in PowerShell.
#if DEBUG
// Debug code
#endif
Upvotes: 9
Views: 9121
Reputation: 390
Example template script with backward compatibility (and a little commenting)
# 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"
So, like we do the check, you could do something like:
[CmdletBinding()]
Param()
# ... some code here creating variables or whatnot ...
if ($DebugPreference -ne "SilentlyContinue") {
# in debug
$messageProperties.To = "$env:[email protected]"
} else {
# not debug
$messageProperties.To = "[email protected]"
}
Upvotes: 1
Reputation: 3451
"Debugged" in PowerShell could mean several things. 1) The program is running under a debugger, 2) The cmdlet/function is passed -Debug
flag or $DebugPreferences
is not SilentlyContinue
3) PowerShell tracing is on, 4) Set-PSDebug was used to toggle tracing (a different kind of tracing than #3).
If you haven't chosen one of these already, I suggest you pick #2. It is straightforward (check if -Debug
is in PSBoundVariables
or value of $DebugPreferences
is not SilentlyContinue
). It supports Write-Debug
cmdlet. In general terms, it is the PowerShell-ish way to toggle debug output.
If you really need #1, then as this page explains, implementing a PowerShell debugger at its core is handling two events (Debugger.BreakpointUpdated
and Debugger.DebuggerStop
), so you need to see if there is a handler for these events.
If you need #4, you'll probably need to access private data. The only PowerShell 3.0 command with PSDebug
as the noun is Set-PSDebug
, which means there isn't a cmdlet to return the state of PSDebug
.
If you need #3, then the situation is similar to #4. There aren't cmdlets to return information of what's being traced.
Upvotes: 4
Reputation: 24410
Here's a function which allows you easily check; along with a few options to alter the behaviour.
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))
}
}
Here's some code to demonstrate output in certain scenarios:
#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
Here's the output from the above:
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
Upvotes: 7