1

my $PSVersionTable output is as follows:

Name                           Value
----                           -----
PSVersion                      7.0.1
PSEdition                      Core
GitCommitId                    7.0.1
OS                             Microsoft Windows 10.0.19041
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

If I enter

wsl -l | Get-Member

the output informs me that the output type is a String.

If I enter

(wsl -l).GetType()

the output informs me that the output type is Array.

The entire reason I'm looking at this is that I was trying to parse the output of that command and for a long, frustrating time, I was thinking that I was working with a single, contiguous string with embedded carriage return / line feeds, but it appears I'm actually working with an array of strings.

So my question: what do the parentheses around the command do to seemingly change the nature of the output of the executable? Is it that without the parentheses the output from 'wsl -l' is being streamed to Get-Member one line (array element) at a time?

Thank you!

3
  • 2
    It's a string array with or without the parentheses. $var = wsl -l $var.gettype() $var.GetType().basetype.name Array Commented Nov 20, 2020 at 18:14
  • 3
    The pipeline | enumerates the contents of the array, and Get-Member only shows output once per distinct input type - both expressions resolve to an array containing strings :) Commented Nov 20, 2020 at 18:14
  • 2
    If wsl -l outputs a single line, you will have a string. Otherwise it's an array. Commented Nov 20, 2020 at 18:16

1 Answer 1

1

If you want to use Get-Member to inspect an object as-is, you mustn't use the pipeline, because the pipeline auto-enumerates arrays (enumerables), and Get-Member then reports the (distinct set of) types among their elements.

Instead, use Get-Member -InputObject, which reports on arrays (enumerables) as a whole:

Get-Member -InputObject (wsl -l) # -> shows the members of type System.Object[]

PowerShell streams the stdout output from external programs such as wsl, line by line. That is, it sends each line as it is being received to the pipeline.

If you assign the command's output to a variable or enclose the command in (), the grouping operator, the stream output is collected:

  • If there's only one output line, a (single) [string] instance is returned.

  • If there are multiple output lines, PowerShell collects them in a regular, [object[]]-typed array for you, whose elements are [string] instances in this case.

If you want to avoid this ambiguity and ensure that the result is always an array, you can use @(), the array-subexpression operator - @(wsl -l) - or, on assigning to a variable, type-constrain that variable as an array - [array] $out = wsl -l


To get a single, potentially multi-line string representation of the output, use the -join operator:

# See note re character encoding below.
(wsl -l) -join "`n"   # or use [Environment]::NewLine instead of "`n"

[Environment]::NewLine returns the platform-appropriate newline char. / sequence, i.e. LF-only ("`n") on Unix-like platforms, CRLF ("`r`n") on Windows. However, PowerShell happily accepts either form on all platforms.

Note:

  • wsl.exe meta commands such as -l, i.e. commands that provide information about or relate to managing distributions (as opposed to interacting with a given distribution) by default output "Unicode", i.e. UTF-16LE-encoded strings; in order for PowerShell to interpret them correctly, additional work is needed - see this answer. In the simplest case, make sure that $env:WSL_UTF8 = 1 is in effect.

  • If you're using PowerShell (Core) 7, you can alternatively use the Join-String cmdlet:

    wsl -l | Join-String -Separator "`n"
    
  • While the Out-String cmdlet would return a single, multi-line string too, it invariably adds a trailing newline (and if you were to use -NoNewLine, it wouldn't use any newlines); this surprising behavior is the subject of GitHub issue #14444.

Sign up to request clarification or add additional context in comments.

2 Comments

Note that wsl outputs utf16 text as well, for example wsl -l | select-string l.i.n.u.x
Good point, @js2010: I've updated the answer accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.