Clean coding with Write-Verbose
It’s a good practise to use the Write-Verbose,Write-Debug and other about_CommonParameters when writing functions because it helps you to write clean code in a very integrated way with Powershell. One of its main benefits is for debugging and verbosing without needing to modify your code.
I’ll focus on the usage of Write-Verbose
. The others have a similar behaviour. The description in technet help is:
The Write-Verbose cmdlet writes text to the verbose message stream in Windows PowerShell.
Typically, the verbose message stream is used to deliver information about command processing that is used for debugging a command.
By default, the verbose message stream is not displayed, but you can display it by changing the value of the $VerbosePreference variable or using the Verbose common parameter in any command.
Values available for $VerbosePreference
:
-SilentlyContinue: Nothing is written. Default value.
-Continue: writes the verbose messages.
More information about $VerbosePreference
can be found in about_Preference_Variables. Note that the Verbose parameter overrides the value of the $VerbosePreference
variable for the current command.
Simple example
This shows the behaviour of Verbose parameter:
Write-Output "Examples using Write-Verbose:"
$VerbosePreference = "SilentlyContinue" # default value
Write-Verbose -message "Log with VerbosePreference=$VerbosePreference without Verbose switch. Not shown."
Write-Verbose -message "Log with VerbosePreference=$VerbosePreference with Verbose switch. Shown." -verbose
$VerbosePreference = "Continue"
Write-Verbose -message "Log with VerbosePreference=$VerbosePreference without Verbose switch. Shown."
Write-Verbose -message "Log with VerbosePreference=$VerbosePreference with Verbose switch disabled. Not shown." -verbose:$false
# Remember to set the default value again
$VerbosePreference = "SilentlyContinue"
The conclusion would be that it writes to the output when $VerbosePreference = "Continue"
or when the -verbose
is used.
Verbose in functions
And it’s when it’s used in functions when it gets really interesting:
# using a normal function. A $verbose parameter is needed
function Write-InVerboseModeSimpleFunction ([string] $text, [switch] $verbose)
{
Write-Verbose $text -verbose:$verbose
}
# Using the advanced functions Param()
# There's no need to specify Verbose parameter because it's a common parameter
function Write-InVerboseMode
{
[CmdletBinding()]
Param
(
[parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String]
$text
)
Process
{
Write-Verbose $text
}
}
Note: one of the implications of using [CmdletBinding()]
is that it avoid extra arguments in functions or script. I like it.
Write-Output "Examples using Write-Verbose in functions:"
$VerbosePreference = "SilentlyContinue"
Write-InVerboseModeSimpleFunction "Write-InVerboseModeSimpleFunction - VerbosePreference=$VerbosePreference without Verbose switch. Not shown."
Write-InVerboseModeSimpleFunction "Write-InVerboseModeSimpleFunction - VerbosePreference=$VerbosePreference with Verbose switch. Shown." -Verbose
Write-InVerboseModeSimpleFunction "Write-InVerboseModeSimpleFunction - VerbosePreference=$VerbosePreference with Verbose switch set to false! Not shown." -Verbose:$false
Write-InVerboseMode "Write-InVerboseMode - VerbosePreference=$VerbosePreference without Verbose switch. Not shown."
Write-InVerboseMode "Write-InVerboseMode - VerbosePreference=$VerbosePreference with Verbose switch. Shown." -Verbose
Write-InVerboseMode "Write-InVerboseMode - VerbosePreference=$VerbosePreference with Verbose switch set to false! Not shown." -Verbose:$false
$VerbosePreference = "Continue"
Write-InVerboseMode "Write-InVerboseMode - VerbosePreference=$VerbosePreference Without Verbose switch. Shown."
Write-InVerboseModeSimpleFunction "Write-InVerboseModeSimpleFunction - VerbosePreference=$VerbosePreference Without Verbose switch. Not shown."
$VerbosePreference = "SilentlyContinue"
But there’s a huge difference: Write-InVerboseModeSimpleFunction
doesn’t work with the preference variable $VerbosePreference
. In the screenshot only appears.
Real life example
This is the prove that the best option is the use of advanced functions. Params()
use permits to set other interesting options: validate not null or empty inputs, mandatory parameters, etc…
Now a real example to see the benefits:
function Add-TwoNumbers
{
[CmdletBinding()]
Param
(
[parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[int]
$numberOne,
[parameter(Position=1, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[int]
$numberTwo
)
Process
{
Write-Verbose "First parameter: $numberOne"
Write-Verbose "Second parameter: $numberTwo"
$result = $numberOne + $numberTwo
Write-Verbose "The result of adding them: $result"
return $result
}
}
Write-Output "`n`n`nReal world example using Write-Verbose in functions:"
Write-Output "`nCalling without verbose: Add-TwoNumbers 4 5"
Add-TwoNumbers 4 5
Write-Output "`nCalling with verbose: Add-TwoNumbers 10 3"
Add-TwoNumbers 10 3 -Verbose
$VerbosePreference = "Continue"
Write-Output "`nCalling with VerbosePreference = Continue: Add-TwoNumbers 8 2"
Add-TwoNumbers 8 2
$VerbosePreference = "SilentlyContinue"
Conclusion
To verbose a script, the easiest way is to set $VerbosePreference = "Continue"
at the beginning of the script or run it with Verbose swicth. In case of using Powershell interactively from Powershell console, to verbose a function or cmdlet the -verbose switch is a good option.
This is a standard in Powershell that helps you to write clean and maintainable code. There’s no need to write strange and own build functions and variables.