Командлет, который возвращает несколько объектов, какой это тип коллекции, если таковая имеется? [PowerShell]

Пример командлета Get-ADuser:

$Users = Get-ADuser -Filter *

В большинстве случаев он будет возвращать несколько объектов ADuser, но какой это тип "коллекции"? В документации только сказано, что он вернет один или несколько пользовательских объектов Microsoft.ActiveDirectory.Management.ADUser.

Пытался использовать, например, ($Users -is [System.Collections.ArrayList]) а я не могу прибить тип "сборник"?


person MrCalvin    schedule 01.02.2020    source источник


Ответы (2)


Командлеты сами обычно используют no тип коллекции в своих выводах. [1]:
Они выдают < em> отдельные объекты в конвейер, что может ситуативно означать: 0 (нет), 1 или несколько.

Это именно то, что делает Get-ADUser: конкретное количество объектов вывода зависит от заданных аргументов; поэтому в Get-AdUser разделе справки упоминается только скалярная введите ADUser в качестве типа вывода и состояния что он возвращает один или несколько из них.

Как правило, конвейер PowerShell представляет собой поток объектов, конкретная длина которого (количество объектов) не требуется заранее знать, а команды в последующих сегментах конвейера обрабатывают предыдущие объекты вывода сегмента один за другим по мере их получения (см. about_Pipelines).


Однако это движок PowerShell, который автоматически собирает для вас несколько выходных данных в [object[]] массив [2] при необходимости. , особенно если вы захватываете вывод с помощью назначения переменной или используете вызов команды через (...), оператор группировки (или $(...), оператор подвыражения [3] < / sup>) как выражение:

# Get-ChildItem C:\Windows has *multiple* outputs, so PowerShell
# collects them in an [object[]] array.
PS> $var = Get-ChildItem C:\Windows; $var.GetType().Name
Object[]

# Ditto with (...) (and also with $(...) and always with @(...))
PS> (Get-ChildItem C:\Windows).GetType().Name
Object[]

Однако, если данная команда - возможно, ситуативно - выводит только единственный объект, тогда вы получите только этот объект сам < / strong> - он не заключен в массив:

# Get-Item C:\ (always) returns just 1 object.
PS> $var = Get-Item C:\; $var.GetType().Name
DirectoryInfo # *not* a single-element array, 
              # just the System.IO.DirectoryInfo instance itself

Что может оказаться сложным, так это то, что данная команда может ситуативно производить один или несколько выходных данных, в зависимости от входных данных и условий выполнения, поэтому движок может возвращать либо один объект , либо множество.

# !! What $var receives depends on the count of subdirs. in $HOME\Projects:
PS> $var = Get-ChildItem -Directory $HOME\Documents; $var.GetType().Name
??? # If there are *2 or more* subdirs: an Object[] array of DirectoryInfo instances.
    # If there is only *one* subdir.: a DirectoryInfo instance itself.
    # (See below for the case when there is *no* output.)

@(), оператор подвыражения массива, предназначен для устранения этой двусмысленности, если это необходимо: заключая команду в @(...), PowerShell гарантирует, что ее вывод всегда собраны как [object[]] - даже если команда создает только один объект вывода или даже ни одного:

PS> $var = @(Get-ChildItem -Directory $HOME\Projects); $var.GetType().Name
Object[] # Thanks to @(), the output is now *always* an [object[]] array.

При назначении переменных потенциально более эффективной альтернативой является использование [array] ограничения типа, чтобы выходные данные превратились в массив:

# Alternative to @(...)
PS> [array] $var = Get-ChildItem -Directory $HOME\Documents; $var.GetType().Name
Object[]

Примечание:

  • Это потенциально более эффективно, поскольку, если RHS уже является массивом, он назначается как есть, тогда как @(...) фактически перечисляет вывод из ..., а затем повторно собирает элементы в массив new ([object[]]).

    • [array] preserves the specific type of an input array by simply passing it through (e.g., [array] $var = [int[]] (1..3) stores the [int[]] array as-is in $var).
  • Размещение преобразования [array] слева от $var = ... - что делает его ограничением типа для переменной - означает, что тип переменной заблокирован в , а присвоение других значений $var позже продолжит преобразование значения RHS в [array] ([object[]]), если это необходимо (если вы не назначите $null или ничего (см. ниже)).


Если команда выводит no, вы ничего не получите (строго говоря: _ 31_ singleton), который в большинстве случаев ведет себя как $null [4] < / sup>:

# Get-Item nomatchingfiles* produces *no* output.
PS> $null -eq (Get-Item nomatchingfiles*)
True

# Conveniently, PowerShell lets you call .Count on this value, which the
# behaves like an empty collection and indicates 0.
PS> (Get-Item nomatchingfiles*).Count
0

[1] можно выводить в конвейер целые коллекции целиком (в коде PowerShell с Write-Output -NoEnumerate $collection или, более кратко, , $collection), но это затем просто еще один объект в конвейере, который сам является коллекцией. Вывод коллекций в целом является аномалией, однако он меняет способ просмотра вывода командами на, что может быть неожиданным; ярким примером является ConvertFrom-Jsons неожиданное поведение до версии 7.0.

[2] экземпляр System.Array, элементы которого типа System.Object, что позволяет смешивать объекты разных типов в одном массиве.

[3] Обычно достаточно использовать (...); $(...) требуется только для интерполяции строк (расширяемые строки) и для встраивания целых операторов или нескольких команд в большее выражение; обратите внимание, что $(...), в отличие от (...), разворачивает одноэлементные массивы; сравните (, 1).GetType().Name с $(, 1).GetType().Name; см. этот ответ.

[4] Существуют сценарии, в которых ничто не отличается от $null, особенно в конвейере и в операторах switch, как подробно описано в этот комментарий на GitHub; связанная проблема - это запрос функции, чтобы ничто не было легче отличить от $null, путем поддержки -is [AutomationNull] в качестве теста.

person mklement0    schedule 01.02.2020

Обычно это просто массив объектов:

$Users.gettype()
$Users.count
$Users -is [object[]]

$ error - это Arraylist:

$error -is [collections.arraylist]
person js2010    schedule 01.02.2020