2

I would like to add an asterisk to the beginning of liner in output:

$SYSLST1 = "OsName","OsVersion","TimeZone","CsName"
$X = (Get-ComputerInfo -Property $SYSLST1 | Format-List | Out-String).Trim()
$Y = ForEach ($Z in $X){
$Z.insert(0,"  * ")
}
Write-Host $Y

But it's only doing the first line:

  * OsName    : Microsoft Windows Server 2016 Standard
OsVersion : 10.0.14393
TimeZone  : (UTC-05:00) Eastern Time (US & Canada)
CsName    : SIS-2016-INT-ST
mklement0
  • 382,024
  • 64
  • 607
  • 775
Ed Pollnac
  • 121
  • 1
  • 6

2 Answers2

3

You need the -Stream switch to instruct Out-String to output individual lines - by default, you'll get a single, multi-line string.

Also, you can simplify your string-insertion task with the help of the -replace operator:

(
  Get-ComputerInfo -Property $SYSLST1 | Format-List | Out-String -Stream
).Trim() -ne '' -replace '^', '  * '
  • -ne '' filters out the empty lines that result from calling .Trim() on all output lines (via member-access enumeration).

  • -replace '^', ' * ', replaces the start of the string (^) with the specified string, in effect inserting it at the beginning of each line.

Generally speaking, note that Format-* cmdlets output objects whose sole purpose is to provide formatting instructions to PowerShell's output-formatting system (which in your case are interpreted by Out-String) - see this answer.

In short: use Format-* cmdlets to format data for display, not for subsequent programmatic processing.

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

Elaborating on @mklement0's answer --

In my experience, PowerShell works best when you can defer formatting until the very end -- i.e. all processing should be done on objects, and then the final task is rendering strings.

Starting at the most basic script:

Get-ComputerInfo -Property $SYSLST1
OsName                                 OsVersion  TimeZone                               CsName
------                                 ---------  --------                               ------
Microsoft Windows Server 2019 Standard 10.0.17763 (UTC-08:00) Pacific Time (US & Canada) WIN-IJ0UD3SK4HR

The result is a single System.Management.Automation.PSCustomObject and by default, the object is run through Format-Table

A cool trick of PSCustomObject is that you can iterate over its properties:

 $(Get-ComputerInfo -Property $SYSLST1).PSObject.Properties |
   ForEach-Object { "  *  $($_.Name) : $($_.Value))" }
  *  OsName : Microsoft Windows Server 2019 Standard)
  *  OsVersion : 10.0.17763)
  *  TimeZone : (UTC-08:00) Pacific Time (US & Canada))
  *  CsName : WIN-IJ0UD3SK4HR)

This gives us full control over the string rendering and allows us to make tweaks to it without fear of breaking other parts of the script.