Why this
Get-WinUserLanguageList | Where-Object LanguageTag -eq en-US
returns empty list (seems it does not filter values) but this
(Get-WinUserLanguageList) | Where-Object LanguageTag -eq en-US
does work? Usually I don't need ()
but in this case they are mandatory, but why?
Usually I don't need () but in this case they are mandatory, but why?
(...)
forces enumeration of the elements of a collection output by the enclosed command in a pipeline.
This shouldn't be necessary, but is in your case, because Get-WinUserLanguageList
exhibits nonstandard behavior: instead of outputting multiple result objects one by one to the pipeline, it emits an entire collection[1] as a single output object.
(...)
, the command in the next pipeline segment - Where-Object
in your case - therefore receives just one input - the entire collection - and operates on it rather than on the elements one by one.LanguageType
property, nothing matches, and you get no output.[2]As mentioned in the comments, you can pipe a command's output to Get-Member
to see the (distinct) types of its output objects; for standard cmdlets, you'd see the types of the individual objects output, not a collection type.
[1] Specifically, the collection is a generic list of type [System.Collections.Generic.List[Microsoft.InternationalSettings.Commands.WinUserLanguage]]
.
[2] You're using simplified syntax in your command - Where-Object LanguageType -eq en-US
- instead of the more verbose, but more flexible script-block syntax - Where-Object { $_.LanguageType -eq 'en-US' }
. Had you used the latter, your command would have accidentally returned the entire collection and thereby effectively all languages. The reason is that only the script-block syntax applies member-access enumeration to the input collection, which means that even though $_
itself doesn't have a .LanguageTag
property, the elements do, and their values are returned as an array. With an array as the LHS, -eq
acts as a filter, and as long as en-US
is among the values returned, the -eq
operation will still be considered $true
, causing the input object - the entire collection - to be passed through.
This surprising discrepancy in behavior between the two seemingly equivalent syntax form is discussed in GitHub issue #9576.