Use PowerShell to Write Verbose Output

Use PowerShell to Write Verbose Output

  • Comments 4
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to write verbose output.

 

Hey, Scripting Guy! Question Hey, Scripting Guy! The other day, you said that I should not use Write-Host. I even read that such usage is dangerous to the health of small canines in 2012 Scripting Games Commentary: STOP USING WRITE-HOST!.

—BP

Hey, Scripting Guy! Answer Hello BP,

Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sipping a cup of English Breakfast tea with a cinnamon stick and a squeeze of lemon. I am using my Surface Pro 2 to check my scripter@microsoft.com email, and I saw another email from you. I decide to crank up Alan Parsons on my 64-gig Zune HD, and dive right in.

Use Write-Verbose

To provide status updates, detailed tracking information, and the like, use the Write-Verbose cmdlet The cool thing about using Write-Verbose is that I never need to modify the script. For example, if I use a whole bunch of Write-Host statements, eventually I may become tired of the clutter. But with Write-Verbose, I can turn on the extra output only if I decide I need it. In addition, because Write-Verbose writes to the verbose output stream, I can decide if I want to capture that output. This makes it a great option.

Easy way to Write-Verbose

By default, Windows PowerShell is set up to use Write-Verbose. The issue is that out of the box, verbose messages do not display. The $VerbosePreference preference variable controls if Write-Verbose statements appear. By default, the value of $VerbosePreference is set to SilentlyContinue, which means the messages do not appear. Because this is a simple preference variable, all I need to do is to change it in my profile. Now all verbose messages will appear in the output. This is probably not a good idea. If I want to change it, the statement is this:

$VerbosePreference = "continue"

If I do not want to make the change in my profile (we really, really do not want to make this change in our profiles), I can easily change it in my script. To do this, I first read the old value of $verbosePreference, store that in a variable, and then change $verbosePreference to continue. Here is the command to do this:

  $oldverbose = $VerbosePreference

  $VerbosePreference = "continue"

Now, when I am done doing whatever I need to do, I simply set the old value. Here is that command:

$VerbosePreference = $oldverbose

To put this into a function, I create a switched parameter named $verbose, and if I call that parameter, I change the existing value of $verbosePreference to continue, and then I can use Write-Verbose to display progress, updates, and other information. Here is the complete function:

Function test-verbose

{

 Param ([switch]$verbose)

 if($verbose) {

   $oldverbose = $VerbosePreference

   $VerbosePreference = "continue" }

 Write-Verbose "verbose output"

 "Regular output"

 $VerbosePreference = $oldverbose

 }

This is pretty simple. When I call the function the first time, only regular output displays. When I call the function with –verbose, the verbose output appears along with the regular output. This is shown in the following image:

Image of command output

Easier way to verbose output

The point of the earlier command is to show you how the preference variables effect the way Write-Verbose works. (It is the same thing for other cmdlets, such as Write-Debug). But there is a slightly easier way to do this, and it is to use the [cmdletbinding()] attribute.

Note  There is a bit of confusion because that I must include Param() in my function—even if I am not accepting parameterized input to the function. The reason is that I am using [cmdletbinding()] as an attribute for my parameters. It does more than turn on automatic support for Write-Verbose. See the following topic (which, incidentally, does not say anything about Write-Verbose) for details: about_Functions_CmdletBindingAttribute.

All I need to do is add the [cmdletbinding()] attribute over the Param() statement, and I automatically gain support for Write-Verbose. Here is the command:

Function Test-VerboseTwo

{

 [cmdletbinding()]

 Param()

 Write-Verbose "Verbose output"

 "Regular output"

}

This is seven lines as opposed to ten lines of script. It saves me three lines. Of course, [cmdletbinding()] does more than automatically wire Write-Verbose, so the savings are potentially greater. To be honest, the script is not quite as easy to read, and [cmdletbinding()] (which does not appear via Tab expansion in the ISE, nor does it really tell me what it is doing) behaves more like a black box. But hey, there is a whole topic that tells me what this little attribute does, so it is not really a black box.

Here is the new function in action:

Image of command output

It is all good, and pretty simple. Perhaps best of all, no small canines were harmed.

BP, that is all there is to writing verbose output. Script Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • There is no need to touch $VerbosePreference!
    Simply use the -verbose Parameter with the Write-Verbose cmdlet.
    Example:
    Write-Verbose 'My verbose message to you' -verbose

  • Now I understand the don't use write-host thing... :) I can just leave my debugging statements in there now.

  • thank you