Problem
You want to display messages and other information to the user.
Solution
To ensure that the output actually reaches the screen, call the WriteHost (or OutHost) cmdlet:
PS >function GetDirectorySize >> { >> $size = (GetChildItem | MeasureObject Sum Length).Sum >> WriteHost ("Directory size: {0:N0} bytes" f $size) >> } >> PS >GetDirectorySize Directory size: 46,581 bytes PS >$size = GetDirectorySize Directory size: 46,581 bytes
If you want a message to help you (or the user) diagnose and debug your script, use the WriteDebug cmdlet. If you want a message to provide detailed tracetype output, use the WriteVerbose cmdlet, as shown in Example 122.
Example 122. A function that provides debug and verbose output
PS >function GetDirectorySize >> { >> WriteDebug "Current Directory: $(GetLocation)" >> >> WriteVerbose "Getting size" >> $size = (GetChildItem | MeasureObject Sum Length).Sum >> WriteVerbose "Got size: $size" >> >> WriteHost ("Directory size: {0:N0} bytes" f $size) >> } >> PS >$DebugPreference = "Continue" PS >GetDirectorySize DEBUG: Current Directory: D:\lee\OReilly\Scripts\Programs Directory size: 46,581 bytes PS >$DebugPreference = "SilentlyContinue" PS >$VerbosePreference = "Continue" PS >GetDirectorySize VERBOSE: Getting size VERBOSE: Got size: 46581 Directory size: 46,581 bytes PS >$VerbosePreference = "SilentlyContinue"
Discussion
Most scripts that you write will output richly structured data, such as the actual count of bytes in a directory. That way, other scripts can use the output of that script as a building block for their functionality.
When you do want to provide output specifically to the user, use the WriteHost, WriteDebug, and WriteVerbose cmdlets.
However, be aware that this type of output bypasses normal file redirection, and is therefore difficult for the user to capture. In the case of the WriteHost cmdlet, use it only when your script already generates other structured data that the user would want to capture in a file or variable.
Most script authors eventually run into the problem illustrated by Example 123 when their script tries to output formatted data to the user.
Example 123. An error message caused by formatting statements
PS >## Get the list of items in a directory, sorted by length PS >function GetChildItemSortedByLength($path = (GetLocation)) >> { >> GetChildItem $path | FormatTable | Sort Length >> }
Example 123. An error message caused by formatting statements (continued)
>> PS >GetChildItemSortedByLength outlineoutput : Object of type "Microsoft.PowerShell.Commands.Internal.Fo rmat.FormatEntryData" is not legal or not in the correct sequence. This is likely caused by a userspecified "format*" command which is conflicting with the default formatting.
This happens because the Format* cmdlets actually generate formatting information for the OutHost cmdlet to consume. The OutHost cmdlet (which PowerShell adds automatically to the end of your pipelines) then uses this information to generate formatted output. To resolve this problem, always ensure that formatting commands are the last commands in your pipeline, as shown in Example 124.
Example 124. A function that does not generate formatting errors
PS >## Get the list of items in a directory, sorted by length PS >function GetChildItemSortedByLength($path = (GetLocation)) >> { >> ## Problematic version >> ## GetChildItem $path | FormatTable | Sort Length >> >> ## Fixed version >> GetChildItem $path | Sort Length | FormatTable >> } >> PS >GetChildItemSortedByLength
(...)
Mode
LastWriteTime
Length Name
a
3/11/2007
3:21 PM
59 LibraryProperties.ps1
a
3/6/2007
10:27 AM
150 GetTomorrow.ps1
a
3/4/2007
3:10 PM
194 ConvertFromFahrenheitWithout
Function.ps1
a
3/4/2007
4:40 PM
257 LibraryTemperature.ps1
a
3/4/2007
4:57 PM
281 ConvertFromFahrenheitWithLib
rary.ps1
a
3/4/2007
3:14 PM
337 ConvertFromFahrenheitWithFunc
tion.ps1
(...)
When it comes to producing output for the user, a common reason is to provide progress messages. PowerShell actually supports this in a much richer way, through its WriteProgress cmdlet.