I was looking for a way to determine whether I was in Verbose mode in Powershell. My web searches came up with various solutions that all suffer from problems. Most of them use $PSBoundParameters. The most obvious problem with this is that it only works when -Verbose was called directly on the script or function whose context you’re currently in. Since the Verbose state is inherited by child scopes, this is less than ideal.

What is Verbose anyway?

For this, it’s best to see the documentation on Preference Variables:

Determines how Windows PowerShell responds to verbose messages 
generated by a script, cmdlet or provider, such as the messages
generated by the Write-Verbose cmdlet. Typically, verbose messages
describe the actions performed to execute a command. 

By default, verbose messages are not displayed, but you can change
this behavior by changing the value of $VerbosePreference.
You can also use the Verbose common parameter of a cmdlet to display
or hide the verbose messages for a specific command. For more
information, type: "get-help about_commonparameters".
Valid values:
    Displays the verbose message and an error
    message and then stops executing.
    Displays the verbose message and then 
    displays a prompt that asks you whether you
    want to continue.
    Displays the verbose message and then continues with execution.
    Does not display the verbose message. Continues executing.

From this we can see that it’s not actually a binary state, but a collection of 4 possible settings with different behavior.

When a script or function is called with -Verbose, it sets the $VerbosePreference variable in that scope to Continue.

If the function is not called with -Verbose, then it can still inherit $VerbosePreference from its parent scope, which could have had it set explicitly or implicitly from anywhere up the stack. $VerbosePreference might also have been set manually to Stop or Inquire.

Testing for Verbosity

So in order to test, you can just check the current value of $VerbosePreference to see which of the 4 states it’s in. Or a more simple boolean check might look like this:

$VerbosePreference -ne [System.Management.Automation.ActionPreference]::SilentlyContinue

Before realizing this, I came up with another one-liner:

[bool](Write-Verbose ([String]::Empty) 4>&1)

This one works by writing something on the verbose stream, redirecting it to stdout, and then casting it to [bool]. This check is nice because it implicitly uses the same criteria as Write-Verbose does. It still feels a bit wrong to me though.

Wrapping Up

Either of these can be wrapped into a small function:

function Test-Verbose {
	[bool](Write-Verbose ([String]::Empty) 4>&1)
function Test-Verbose {
	[System.Management.Automation.ActionPreference]::SilentlyContinue -ne $VerbosePreference

From what I can tell, both of these tests work in all of the following situations:

  • Explicitly calling the current function with -Verbose

  • The above (but calling a script)

  • Inheriting $VerbosePreference from a parent scope

  • Explicitly setting $VerbosePreference

  • Explicitly undoing an existing state with -Verbose:$false

This should all apply to -Debug and $DebugPreference as well, but I haven’t tested. Let me know if you do!