This morning there was some discussion on Twitter about when to use Write-Verbose and when to use Write-Debug. They both can provide additional information about what your script or function is doing, although you have to write the code. Typically, I use Write-Verbose to provide trace and flow messages. When enabled, it makes it easier to follow what the script is doing and often the messages include variable information. Write-Debug is helpful for providing detailed debug messages, but it also has the effect of turning on debuggging when you include it.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Here's a sample script that uses both cmdlets.
[cc lang="PowerShell"]
#requires -version 2.0
[cmdletbinding()]
Param([string]$computername=$env:computername)
$start=Get-Date
Write-Verbose "Starting $($myinvocation.mycommand)"
Write-Debug "`$computername is $computername"
Write-Verbose "Connecting to $computername"
Try {
Write-Debug "Trying WMI"
$cs=get-wmiobject -class win32_computersystem -ComputerName $computername -errorAction Stop
}
Catch {
Write-Debug "Exception caught"
Write-Warning ("Failed to get WMI information from $computername. {0}" -f $_.Exception.Message)
}
if ($cs) {
Write-Verbose "Processing Results"
Write-Debug ($cs | Select * | Out-string)
$cs | Select Model,Manufacturer
}
$end=Get-Date
Write-Debug ("Total processing time {0}" -f ($end-$start).ToString())
Write-Verbose "Ending $($myinvocation.mycommand)"
[/cc]
The script can use the common -Verbose and -Debug common parameters because I include the [cmdletbinding()] attribute. You don't need to define the parameters. When I run the script normally it runs as expected.
[cc lang="DOS"]
PS S:\> .\debugdemo.ps1
Model Manufacturer
----- ------------
Qosmio X505 TOSHIBA
[/cc]
When I use -Verbose, all the Write-Verbose commands "work".
The -Debug parameter does the same thing for Write-Debug, but it also turns on debugging:
Not only do I get the Write-Debug messages, but I get a prompt for every command. I can drop into the debug prompt using the Suspend option and look at variables or run any other PowerShell commands. Some 3rd party script editors, like PrimalScript, also take advantage of Write-Debug messages. I can load the script into the editor and run it with Debug turned on (F7 or F5) and the debug messages show in the Debug window.
This ability to step through a script is very handy, but often (personally) I just need to see where I'm at in the script and Write-Verbose suffices. As you see you can have both types of commands, and you can certainly run the script with both parameters. One last note, both cmdlets require that the message be a string. When I want to write objects using either Write-Debug or Write-Verbose, I use expressions like this:
[cc lang="PowerShell"]
Write-Debug ($cs | Select * | Out-string)
[/cc]
I encourage you to include Verbose/Debug messages from the very beginning of your script development. You only see the messages when you use the appropriate parameter. It may seem like a lot of work up front, but when the time comes to debug or trace a problem, you'll realize it was time well spent.
The key difference is that -Verbose sets $VerbosePreference to “Continue” inside the block, but -Debug sets $DebugPreference to “Inquire”:
# By default, these each print out "SilentlyContinue"
$VerbosePreference; $DebugPreference;
# But inside here they'll print out "Continue" and "Inquire"
&{ [CmdletBinding()]param() $VerbosePreference; $DebugPreference} -verbose -debug
I’ll admit that I frequently with they had made those like the -ErrorAction and -WarningAction parameters which take a value so you can choose what you want.
I use a VBscript template that allows me various levels of verbosity so I rather like using Write-Verbose and Write-Debug to control the output. The constant enquiry can get annoying though so I add this code to the top of my template to give me a little more control:
Param ([switch]$inquire = $false)
if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey("debug")) {
if (-not $inquire) {$DebugPreference="Continue"}
}
This turns off the inquiry by default, but lets me add it back in with the -inquire switch if I feel the need.
Excellent. Once Joel filled me in on what was happening under the hood I figured I could try something like this. This is a very handy technique.
Nice post – thanks Jeffrey.
I too like the approach that Russ details above of adding an additional switch to control the enquiry in debug mode. I didn’t know that you could query the parameter set in that way, so that’s two handy tips in one!
Hi Jeffery, My apologies for misspelling your name – could you edit it on moderation please? Thanks, Nigel
Don’t worry about it. Thanks for the comment.