Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store output from Format-Table for later use

Tags:

powershell

I have a script that creates several jobs and stores two simple values in the jobs.

Start-Job -ScriptBlock {param ([string]$compip) tnc $compip | select RemoteAddress,PingSucceeded -WarningAction SilentlyContinue} -ArgumentList $compip

This works fine. What I would like to know is how can I store the following code into a variable?

Get-Job | Receive-Job | sort RemoteAddress | FT

I have tried this, but it does not work as I thought it would:

$pcs = Get-Job | Receive-Job | sort RemoteAddress | FT
$pcs.RemoteAddress

Am I going at this the wrong way? I would like to store the data from the get-job command above to use the values later in the script. I assumed it would work because the output looks correct: Command:

Get-Job | Receive-Job | sort RemoteAddress | FT

Output:

RemoteAddress PingSucceeded                        
------------- -------------                         
192.168.0.163          True
192.168.0.101          False
192.168.0.2            False
192.168.0.251          True 
like image 312
Webtron Avatar asked Apr 01 '16 13:04

Webtron


1 Answers

Problem with Format-cmdlets

The issue here is your use of FT which is an alias for Format-Table. These Format- cmdlets are designed for console/screen output only. There are many things you can do with them to tailor that output but in every case PowerShell needs to massage the data in order to be able to do so. This includes breaking down to the passed objects into groups of different objects...

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

The above data types were extract from running this code.

Get-ChildItem c:\temp | Format-Table | Get-Member

So you no longer have the System.IO.FileInfo and System.IO.DirectoryInfo objects that you would normally get from Get-ChildItem

Another large issue comes from Format-cmdlets nature to truncated data, like arrays with a large numbers of elements or long strings, to make as much fit on screen. In the case of arrays, this is due to the preference variable $FormatEnumerationLimit which is commonly defaulted to 4.

Ten Numbers                                                                                                                                                  
-----------                                                                                                                                                  
{1, 2, 3, 4...}  

These, and other, limitations can all be mitigated with cmdlet switches like -AutoSize and -HideTableHeaders, out-string -width, etc. That does not matter however because...


Solution

Good news is the solution is very simple. Stop using them for anything other than console output. Using my earlier example:

  • Saving results in a variable?: $result = Get-ChildItem C:\temp

  • Exporting Data: Get-ChildItem C:\temp | Export-CSV $path -NoTypeInformation. Other Export-cmdlets could be preferred here like Export-CLIXml for complex objects when you want to store them for use elsewhere. If you are just looking for something pretty to include in your output then consider ConvertTo-HTML instead.

  • Extracting individual properties?: Just use Select-Object. $result | Select prop1, prop2. You can also expand your property selection to just get the strings or string array with -ExpandProperty: $result | Select -ExpandProperty prop1

  • Performing inline calculations with said properties?: Use calculated expression just as you would with the Format-Cmdlets. $result | Select prop1, @{Name="prop2";Expression={$_.prop2 * 3}


Potential Acceptable Use

Some prefer the output for use in emails and for recording statistics. While it is integral to keep data in its more easily used format for later use. However if you really need that data keep in mind that you are not working with the object your originally had anymore.

So if you needed your data in a table format but stored as a string then consider Out-String

$body = Get-ChildItem c:\temp | Format-Table | Out-String

but remember that Format-Table will play with object output in order to get it to display on screen (truncated array properties and long strings). Really.. if you wanted it nice and formatted then you should just use ConvertTo-HTML.

Point is you almost never need to keep the data from Format-Table. There is almost always a better way.

like image 194
Matt Avatar answered Oct 11 '22 18:10

Matt