In the previous tutorial I introduced to you the basic concept of Redirection and Piping of information via Cmdlets to an eternal file.
PowerShell by default writes the actual Script to the console while executing it, but mote importantly by default will also write command output to the console. Often this is perfectly fine, but there are many occasions where it is better in fact to write command output to a external file which can be more easily analyzed and shared with others should there be a need for this.
Examples of when writing output to an external file may be more useful are when you wish to save text output for review later on, or wish to record specific error messages that may help you resolve an issue with your Operating System or some other application.
If you read Tutorial 4 you will be aware you can pipe output from a Cmdlet then redirect it to a file easily using the following format:
So the Cmdlet on left side of pipe produces an object which is then piped to another Cmdlet which receives that object as input, then creates a new object which is then redirected to an external file.
While this basic redirection can be a little confusing at first to the novice programmer, unfortunately, thing only get trickier for more advanced Scripting in PowerShell owing to the fact PowerShell has multiple ways to Stream a message as output.
Taking this into account PowerShell has a way for you to indicate more specifically the type of redirection you are intending when Scripting the redirection.
I'll get to that shortly, but first let's try using a simple Function to take a look at what each of the above Stream options will do if we only apply the basic Redirect all ready explained in the previous Tutorial or just some of the more advanced redirects not yet explained in full.
Note: You will be creating .txt files in the default directory while trying this function, and will also be prompted to click Yes or Yes to all, two or three times during its execution. Any files created can be safely deleted when you've completed this Tutorial if you wish.
Copy & paste the above into the Script pane in your Windows PowerShell ISE then click File > Run.
As you can see these different types of streamed messages will display on your console in a different colour. This is by design, and if you wanted to you could manipulate the colours using -ForeGroundColor green or what ever colour you want the message displayed in. Obviously, given the default console colour is a mid-dark blue, unless you manually change that colour by the options settings, you will want to select a colour that will be legible on the console.
These same messages being saved to a .txt file will not appear in different colours though. You can confirm that by typing notepad.exe Outputfile.txt into the Windows PowerShell ISE and pressing Enter key
So why the need for Advanced Redirections?
Streams are critical in any language that uses piping.
In PowerShell as already explained you can pipe one object from a Cmdlet to be used as input for another Cmdlet. However, for the receiving Cmdlet to be able to action this input you do not want that receiving Cmdlet to receive errors, warnings, debugging messages, or verbose messages along with the objects that it's designed to process. If it does, its likely to bring your Script to a crashing halt and leave you with some serious debugging to do in order to get your Script to do what you intended it to be doing.
In PowerShell when you use | (the pipe operator), it is actually piping an object down the output stream. The receiving Cmdlet does not see errors, warnings, verbose messages, or debugging messages, because they are sent in other streams.
Windows PowerShell also uses the output stream for assignments, like assigning (i.e. saving data) a value in a variable. This is why you can save an output message in a variable, for example:
However, it is not possible to assign a verbose message to a variable in this way. Look what would happen if you tried using this code:
Attempting to do the impossible results in one heck of an error message!
As a result Microsoft provided some more advanced methods to redirect a Stream message.
So if we relook at our last attempt to save a Verbose message, but apply an advanced redirect instead, then look what happens now.
The impossible has now become possible by using the advanced redirect 4>&1
It's a little difficult to explain this in words, so let's make use of that saying, 'A picture tells a thousand words' — actually two pictures in this case.
Illustration displaying the 5 Stream options in Windows PowerShell
Image displaying what is happening when using advanced redirect 4>&1
Note: You can apply this same thinking to any of the advanced redirect options.
So what are the Advanced Redirect Options?
As there are 5 streams there are naturally five advanced redirect choices plus one extra choice to allow you to redirect all five outputs.
Below is a table showing you these choices:
Below is some illustrations of Advanced redirection, and examples of its use:
Note: More information on this can be found here at the following online resource:
https://docs.microsoft.com/en-us/po...ll.Core/about_Redirection?view=powershell-5.1
Before we go, one last important note.
Earlier in this tutorial I showed you the two examples of messages being streamed to the console and/or .txt files. In the initial example, all messages reached the console, with one exception that was sent to the OutputFile.txt.
Then in the second example by using the redirect 4>&1 we could store data in a variable and print to the console.
Now if you were to make use of the function in those examples, to attempt the following example you would see that all messages would be sent to the OutputFile.txt with the exception of the Write-Host message.
The above code uses the advanced All Output redirect *>
The Cmdlet Write-Host does not in fact get written to any of the Stream options mentioned in this Tutorial. It simply sends the collected data, or attempts to send it, to the Console of either Windows PowerShell ISE, or Windows PowerShell subject obviously to which console you are using at the time.
Thus, you cannot redirect Write-Host messages so if you wish to communicate all streamed messages to the User, you are best to use Write-Verbose as we did in the second example.
Well that brings us to the conclusion of a rather tricky subject. Don't panic if it has not all sunk in yet. The learning curve on this topic is one of those things that really only improves as you apply the techniques in your Scripting.
If you cannot remember all the special items — in this case the 6 ways to do advanced redirection, again, do not panic, as the online resource mentioned in the Tutorial is not going anywhere, so you can easily bookmark it, or if you want print it out and save it.
In the next Tutorial I'll be addressing the user or Operators in PowerShell within arithmetic cases as well as with Commands and Strings. Something a little lighter to study, unless you hate math that is
Regards,
Regedit32
PowerShell by default writes the actual Script to the console while executing it, but mote importantly by default will also write command output to the console. Often this is perfectly fine, but there are many occasions where it is better in fact to write command output to a external file which can be more easily analyzed and shared with others should there be a need for this.
Examples of when writing output to an external file may be more useful are when you wish to save text output for review later on, or wish to record specific error messages that may help you resolve an issue with your Operating System or some other application.
If you read Tutorial 4 you will be aware you can pipe output from a Cmdlet then redirect it to a file easily using the following format:
Code:
Cmdlet | Cmdlet { some parameters & arguments } > $env:Some_Location\File.txt
So the Cmdlet on left side of pipe produces an object which is then piped to another Cmdlet which receives that object as input, then creates a new object which is then redirected to an external file.
While this basic redirection can be a little confusing at first to the novice programmer, unfortunately, thing only get trickier for more advanced Scripting in PowerShell owing to the fact PowerShell has multiple ways to Stream a message as output.
- Write-Host
- Write-Verbose
- Write-Warning
- Write-Error
- Write-Debug
Taking this into account PowerShell has a way for you to indicate more specifically the type of redirection you are intending when Scripting the redirection.
I'll get to that shortly, but first let's try using a simple Function to take a look at what each of the above Stream options will do if we only apply the basic Redirect all ready explained in the previous Tutorial or just some of the more advanced redirects not yet explained in full.
Note: You will be creating .txt files in the default directory while trying this function, and will also be prompted to click Yes or Yes to all, two or three times during its execution. Any files created can be safely deleted when you've completed this Tutorial if you wish.
Code:
# CREDIT: 'The Scripting Guys', Ed Wilson
# Website: https://blogs.technet.microsoft.com/heyscriptingguy/2014/03/30/understanding-streams-redirection-and-write-host-in-powershell/
function Write-Messages {
[CmdletBinding()]
param()
Write-Host "`nHost message`n"
Write-Output "`nOutput message`n"
Write-Verbose "`nVerbose message`n"
Write-Warning "`nWarning message`n"
Write-Error "`nError message`n"
Write-Debug "`nDebug message`n"
}
# Writes all messages to console.
Write-Messages -Verbose -Debug
# Writes output to the .txt file in the current active directory
# Writes all other messages to console.
Write-Messages -Verbose -Debug > .\OutputFile.txt
# Writes all output except Host messages to .txt file in the current active directory
Write-Messages -Verbose -Debug *> .\OutputFile.txt
# Writes all output (except Host messages) to output stream,
# then saves them in a .txt file in Current active directory.
Write-Messages -Verbose -Debug *>&1 | Out-File -FilePath .\OutputFile.txt
# Writes all messages to console and then saves all but host messages in a .txt file,
# in the current active directory.
Write-Messages -Verbose -Debug *>&1 | Tee-Object -FilePath .\OutputFile.txt
Copy & paste the above into the Script pane in your Windows PowerShell ISE then click File > Run.
As you can see these different types of streamed messages will display on your console in a different colour. This is by design, and if you wanted to you could manipulate the colours using -ForeGroundColor green or what ever colour you want the message displayed in. Obviously, given the default console colour is a mid-dark blue, unless you manually change that colour by the options settings, you will want to select a colour that will be legible on the console.
These same messages being saved to a .txt file will not appear in different colours though. You can confirm that by typing notepad.exe Outputfile.txt into the Windows PowerShell ISE and pressing Enter key
So why the need for Advanced Redirections?
Streams are critical in any language that uses piping.
In PowerShell as already explained you can pipe one object from a Cmdlet to be used as input for another Cmdlet. However, for the receiving Cmdlet to be able to action this input you do not want that receiving Cmdlet to receive errors, warnings, debugging messages, or verbose messages along with the objects that it's designed to process. If it does, its likely to bring your Script to a crashing halt and leave you with some serious debugging to do in order to get your Script to do what you intended it to be doing.
In PowerShell when you use | (the pipe operator), it is actually piping an object down the output stream. The receiving Cmdlet does not see errors, warnings, verbose messages, or debugging messages, because they are sent in other streams.
Windows PowerShell also uses the output stream for assignments, like assigning (i.e. saving data) a value in a variable. This is why you can save an output message in a variable, for example:
Code:
$message = Write-Output -Message "Output message"
$message
However, it is not possible to assign a verbose message to a variable in this way. Look what would happen if you tried using this code:
Code:
$message = Write-Verbose -Message "Verbose message" -Verbose VERBOSE: Verbose message
$message
Attempting to do the impossible results in one heck of an error message!
As a result Microsoft provided some more advanced methods to redirect a Stream message.
So if we relook at our last attempt to save a Verbose message, but apply an advanced redirect instead, then look what happens now.
Code:
$message = Write-Verbose -Message "Verbose message" -Verbose 4>&1
$message
The impossible has now become possible by using the advanced redirect 4>&1
It's a little difficult to explain this in words, so let's make use of that saying, 'A picture tells a thousand words' — actually two pictures in this case.
Illustration displaying the 5 Stream options in Windows PowerShell
Image displaying what is happening when using advanced redirect 4>&1
Note: You can apply this same thinking to any of the advanced redirect options.
So what are the Advanced Redirect Options?
As there are 5 streams there are naturally five advanced redirect choices plus one extra choice to allow you to redirect all five outputs.
Below is a table showing you these choices:
Below is some illustrations of Advanced redirection, and examples of its use:
Code:
Operator Description Example [/B][/B][/B]
[B][B][B]-------- ---------------------- ------------------------------
> Sends output to the Get-Process > Process.txt
specified file.
>> Appends the output to dir *.ps1 >> Scripts.txt
the contents of the
specified file.
2> Sends errors to the Get-Process none 2> Errors.txt
specified file.
2>> Appends errors to Get-Process none 2>> Save-Errors.txt
the contents of the
specified file.
2>&1 Sends errors (2) and Get-Process none, Powershell 2>&1
success output (1)
to the success
output stream.
3> Sends warnings to the Write-Warning "Test!" 3> Warnings.txt
specified file.
3>> Appends warnings to Write-Warning "Test!" 3>> Save-Warnings.txt
the contents of the
specified file.
3>&1 Sends warnings (3) and function Test-Warning
success output (1) { Get-Process PowerShell;
to the success Write-Warning "Test!" }
output stream. Test-Warning 3>&1
4> Sends verbose output to Import-Module * -Verbose 4> Verbose.txt
the specified file.
4>> Appends verbose output Import-Module * -Verbose 4>> Save-Verbose.txt
to the contents of the
specified file.
4>&1 Sends verbose output (4) Import-Module * -Verbose 4>&1
and success output (1)
to the success output
stream.
5> Sends debug messages to Write-Debug "Starting" 5> Debug.txt
the specified file.
5>> Appends debug messages Write-Debug "Saving" 5>> Save-Debug.txt
to the contents of the
specified file.
5>&1 Sends debug messages (5) function Test-Debug
and success output (1) { Get-Process PowerShell
to the success output Write-Debug "PS" }
stream. Test-Debug 5>&1
*> Sends all output types function Test-Output
to the specified file. { Get-Process PowerShell, none
Write-Warning "Test!"
*>> Appends all output types Write-Verbose "Test Verbose"
to the contents of the Write-Debug "Test Debug" }
specified file.
Test-Output *> Test-Output.txt
*>&1 Sends all output types Test-Output *>> Test-Output.txt
(*) to the success output Test-Output *>&1
stream.
Note: More information on this can be found here at the following online resource:
https://docs.microsoft.com/en-us/po...ll.Core/about_Redirection?view=powershell-5.1
Before we go, one last important note.
Earlier in this tutorial I showed you the two examples of messages being streamed to the console and/or .txt files. In the initial example, all messages reached the console, with one exception that was sent to the OutputFile.txt.
Then in the second example by using the redirect 4>&1 we could store data in a variable and print to the console.
Now if you were to make use of the function in those examples, to attempt the following example you would see that all messages would be sent to the OutputFile.txt with the exception of the Write-Host message.
Code:
Write-Messages *> .\OutputFile.txt
The Cmdlet Write-Host does not in fact get written to any of the Stream options mentioned in this Tutorial. It simply sends the collected data, or attempts to send it, to the Console of either Windows PowerShell ISE, or Windows PowerShell subject obviously to which console you are using at the time.
Thus, you cannot redirect Write-Host messages so if you wish to communicate all streamed messages to the User, you are best to use Write-Verbose as we did in the second example.
Well that brings us to the conclusion of a rather tricky subject. Don't panic if it has not all sunk in yet. The learning curve on this topic is one of those things that really only improves as you apply the techniques in your Scripting.
If you cannot remember all the special items — in this case the 6 ways to do advanced redirection, again, do not panic, as the online resource mentioned in the Tutorial is not going anywhere, so you can easily bookmark it, or if you want print it out and save it.
In the next Tutorial I'll be addressing the user or Operators in PowerShell within arithmetic cases as well as with Commands and Strings. Something a little lighter to study, unless you hate math that is
Regards,
Regedit32