Programmatically capture Verbose Output in a PowerShell variable

Page content

I was playing around with the cmdlets in the DFSR-module the other day and realized that none of them could (as far as I could tell) give me a reliable count on the number of items in the DFSR Backlog.

My plan was to initiate a replication of two folders and then have a script monitor the backlog to generate status messages to keep me informed of the progress.

I searched for a way to accomplish this by looking at the commands in the DFSR module that have the verb Get

PS C:> Get-Command -Module DFSR -Verb Get

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Get-DfsrBacklog                                    DFSR
Cmdlet          Get-DfsrCloneState                                 DFSR
Cmdlet          Get-DfsrConnection                                 DFSR
Cmdlet          Get-DfsrConnectionSchedule                         DFSR
Cmdlet          Get-DfsReplicatedFolder                            DFSR
Cmdlet          Get-DfsReplicationGroup                            DFSR
Cmdlet          Get-DfsrFileHash                                   DFSR
Cmdlet          Get-DfsrGroupSchedule                              DFSR
Cmdlet          Get-DfsrIdRecord                                   DFSR
Cmdlet          Get-DfsrMember                                     DFSR
Cmdlet          Get-DfsrMembership                                 DFSR
Cmdlet          Get-DfsrPreservedFiles                             DFSR
Cmdlet          Get-DfsrServiceConfiguration                       DFSR
Cmdlet          Get-DfsrState                                      DFSR

The the Get-DfsrBacklog seems just like the thing I’m looking for. Just to make sure I had a look into the help for that cmdlet

and got a little amazed when realizing that it would return the first 100 objects in my replication backlog.

That’s great and all, but what if I want the total count? Are there hundreds or millions of items in the backlog? There is no way (that I could find) to return the total number of objects in the backlog, BUT if the –Verbose switch is used the command will write a message to the Verbose stream stating something similar to:

The replicated folder has a backlog of files. Replicated folder: “ReplFolder”. Count: 46314

or

No backlog for the replicated folder named “ReplFolder”

And there it is folks! Anyone can run the command and read the verbose message. Anyone but my script which couldn’t care less about the Verbose stream. Or does it?

This is where a great little feature in powershell called redirection comes in handy. This feature was introduced already in Powershell version 2.0 but back then it was limited to only redirect two streams, the Success Output (the common output that I usually refer to as pipeline) and the Errors steams. In Powershell version 3.0 it got even more powerful and now we can direct any of the five outputstreams (Success, Error, Warning, Verbose and Debug) to either the success output stream or to a file of our choosing using the redirect operator ‘>’. The syntax is easy, first enter the number of the outputstream that should be redirected from the table below followed by the operator > and the target of the redirection.

<td valign="top" width="137">
  All output
</td>
<td valign="top" width="137">
  Success output
</td>
<td valign="top" width="137">
  Errors
</td>
<td valign="top" width="137">
  Warning messages
</td>
<td valign="top" width="137">
  Verbose output
</td>
<td valign="top" width="137">
  Debug messages
</td>
*
1
2
3
4
5

To test this I wrote a function that will output text to different streams.

function Write-ToStreams
{
    [cmdletbinding()]
    Param()
    Begin
    {
        $VerbosePreference = 'Continue'
        $DebugPreference = 'Continue'
    }
    Process
    {
        Write-Host "This is written to host" -ForegroundColor Green
        Write-Output "This is written to Success output"
        Write-Error "This is an error"
        Write-Warning "This is a warning message"
        Write-Verbose "This is verbose output"
        Write-Debug "This is a debug message"
    }
}

Which gives me the following output:

Write-ToStreams1

Now if I want to redirect my verbose output I’ll end my command with the number of the verbose output stream, ‘4’, followed by the redirect operator ‘>’ and the target of my redirection.

Write-ToStreams2

The other option is to redirect one output stream to the success output stream by using &1 as the target like this:

Write-ToStreams3

Which looks exactly like the first time we ran the command! But this time the verbose message is actually written to the output stream.

To test this let’s store the output in a variable:

Write-ToStreams4

And this is the answer to my problem with the count of files in the DFSR Backlog. I just have to separate the default output from the verbose output.

So lets start over by running the function Write-ToStreams and storing the output in a variable without redirection:

$Output = Write-ToStreams

This would output messages to all streams but the Success output, which would be caught by my $Output variable. To catch the other streams I use another feature called a subexpression. A subexpression is like a scripted variable, for example by writing $(Get-Date –f $FormatString), the code within the parentheses is executed and the result will be returned like it came from a variable. By enclosing out previous example in a subexpression we get the opportunity to redirect the verbose output and capture it in another variable like this:

$VerboseMessage = $($Output = Write-ToStreams) 4>&1

Write-ToStreams5

Which could be repeated for any of the remaining three streams Error, Warning and Debug. A very important thing to notice here is the green text created by Write-Host. This text cannot be redirected or captured at all, which makes Write-Host something that only should be used if the intent is to write something to screen and never ever for actual output. Use any of the other streams for output.

To get back to my problem with the count of items in the dfsr backlog, I wrote a script that will return the number of items in the backlog for each replicated folder using this technique and it is available on the Technet Gallery.

For a more information about redirection, please refer to the help article about_Redirection.