PowerShell

PowerShell – Working with Format-Table in Verbose, Debug, Output Streams

As you may know, PowerShell has multiple streams. You can use those streams using following functions Write-Output, Write-Error, Write-Warning, Write-Verbose, Write-Debug, and Write-Information. It also has Write-Host which until PowerShell 5 was a bit special. Since PowerShell 5.1 it's a wrapper over Write-Information, so it doesn't kill puppies anymore and it's safe to use. While I could spend the next five pages trying to give my best and describe those streams, there are already many articles describing them in detail. Please check the following link if you need that information.

Before you read about Format-Stream you may also be interested in PSWriteColor which provides excellent options for working with colors using Write-Host. But let's not get too distracted. As you may even know there are nice commands that can help you output your HashTables, OrderedDictionary, PSCustomObjects, and many custom ones to a beautiful looking Table or a List. Those are Format-Table and Format-List.

The output from those commands is nice and really useful. But what if you want to use those commands in other streams? Such as Debug? Verbose? Or if you want to send that output to file?

PS C:\Users\pklys> Get-Process | Select-Object -First 5 |Format-List | Add-Content -Path 'C:\testor.txt'
PS C:\Users\pklys> Get-Process | Select-Object -First 5 |Format-Table | Add-Content -Path 'C:\testor.txt'

You would get something like this

Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

And in Debug/Verbose streams it's not available at all. Not useful right? So I've searched for a solution but couldn't find anything that would be enough for me to use. I always had some problems with them. And both Format-Table and Format-List have their benefits. That's where my Format-Stream function comes in that I've written over the weekend.

Format-Stream - What's that?

Format-Streams is supposed to fill the gap and allow you to work with Format-Table / Format-List in Verbose, Debug, Output, Informational and “Host” streams. It's also cross-platform working on Windows, Linux, and Mac. It's part of PSSharedGoods module even thou it could probably do on its own. But since I've recently fixed it's load time from, 12 seconds to 200 milliseconds, it's staying as part of PSSharedGoods module. Which isn't that bad since if you're using any of my other modules such as PSWriteWord, PSWriteExcel, PSAutomator, PSWinReporting you already have it. You just need to update it.

Format-Stream - Verbose

As it stands Format-Stream, by default, outputs Table or List in Verbose mode. Its usage is quite simple, and you mainly use it like you would use Format-Table or Format-List.

Get-Process | Format-Stream

Get-Process | Select-Object -First 1 | Format-Stream -List

Format-Stream - Debug
Get-Process | Select-Object -First 5 | Format-Stream Name, PriorityClass, HandleCount -Stream Debug -List
Get-Process | Select-Object -First 5 | Format-Stream Name, PriorityClass, HandleCount -Stream Debug

As you can see above Format-Stream displays just fine in DEBUG stream in both Table and List modes. If you will give a wildcard or won't define properties at all Format-Stream will try to fill in the maximum size of the screen. You can also define additional parameters such as ExcludeProperty, AlightRight or HideTableHeaders.

Get-Process | Select-Object -First 5 | Format-Stream * -Stream Debug
Get-Process | Select-Object -First 5 | Format-Stream -Stream Debug
Get-Process | Select-Object -First 5 | Format-Stream -Stream Debug -ExcludeProperty Name, SI, Handles -AlignRight -HideTableHeaders
Format-Stream - Output

Like you've probably already noticed each output type behaves similar and works with same parameter sets. There are also Transpose and TransposeSort parameters which allows you to convert PSCustomObject to HashTable and vice versa.

Get-Process | Select-Object -First 5 | Format-Stream * -Stream Output
Get-Process | Select-Object -First 5 | Format-Stream Name,ID -Stream Output -Transpose
Get-Process | Select-Object -First 5 | Format-Stream Name,ID -Stream Output -List

There's one more trick to Output stream. You can output it to file. And it will keep its form.

Get-Process | Select-Object -First 5 | Format-Stream * -Stream Output | Add-Content -Path 'C:\test.txt'
Get-Process | Select-Object -First 5 | Format-Stream Name,ID -Stream Output -Transpose | Add-Content -Path 'C:\test.txt'
Get-Process | Select-Object -First 5 | Format-Stream Name,ID -Stream Output -List | Add-Content -Path 'C:\test.txt'

Format-Streams - Informational and Host output

You can do an exactly the same thing with the Informational stream like with others if you need to. So I won't bother you with showing how and providing a screenshot. Finally, I wanted to show what Host is able to do. Apart from standard functionality that all other streams there's one little, maybe not very configurable feature.

Get-Process | Select-Object -First 5 | Format-Stream * -Stream Host -ForegroundColor Green,Red, Yellow -ForegroundColorRow 2,4,5
Get-Process | Select-Object -First 5 | Format-Stream Name,ID -Stream Host -ForegroundColor Green,Red, Yellow -ForegroundColorRow 2,4,5
Get-Process | Select-Object -First 5 | Format-Stream Name,ID -Stream Host -List

See what I did there? And it's cross-platform for all streams as well. Hope you like it. If there's already something similar on Google I wasn't able to found it. But it was fun to make it work. Enjoy.

Required prerequisites

Before you can use this script, you need to do a few manual steps. Since this script is published as a module, it's quite easy to set this up. Just execute the command below (accept warnings) .. and you can test it out.

Install-Module PSSharedGoods

#Update-Module PSSharedGoods

You can of course install everything manually from GitHub (as everything is published there) but it will be far easier to just use Install-Module.

Alternative method

There also seems a way to do it without Write-Stream using some neat trick with Out-String. Choose your own poison.

Get-Process | Sort-Object WS -Descending | Select-Object -First 10 | Format-Table  | Out-String | Write-Verbose
Get-Process | Sort-Object WS -Descending | Select-Object -First 10 | Format-Table  | Out-String | Write-Debug
Get-Process | Sort-Object WS -Descending | Select-Object -First 10 | Format-Table  | Out-String | Write-Output
Get-Process | Sort-Object WS -Descending | Select-Object -First 10 | Format-Table  | Out-String | Write-Host

Keep in mind that you won't see Debug or Verbose without explicitly asking for it.

This post was last modified on %s = human-readable time difference 01:10

Przemyslaw Klys

System Architect with over 14 years of experience in the IT field. Skilled, among others, in Active Directory, Microsoft Exchange and Office 365. Profoundly interested in PowerShell. Software geek.

Share
Published by
Przemyslaw Klys

Recent Posts

Upgrade Azure Active Directory Connect fails with unexpected error

Today, I made the decision to upgrade my test environment and update the version of…

1 month ago

Mastering Active Directory Hygiene: Automating Stale Computer Cleanup with CleanupMonster

Have you ever looked at your Active Directory and wondered, "Why do I still have…

2 months ago

Active Directory Replication Summary to your Email or Microsoft Teams

Active Directory replication is a critical process that ensures the consistent and up-to-date state of…

7 months ago

Syncing Global Address List (GAL) to personal contacts and between Office 365 tenants with PowerShell

Hey there! Today, I wanted to introduce you to one of the small but excellent…

11 months ago

Active Directory Health Check using Microsoft Entra Connect Health Service

Active Directory (AD) is crucial in managing identities and resources within an organization. Ensuring its…

1 year ago

Seamless HTML Report Creation: Harness the Power of Markdown with PSWriteHTML PowerShell Module

In today's digital age, the ability to create compelling and informative HTML reports and documents…

1 year ago