一个返回多个对象的cmdlet,它是什么集合类型(如果有)? [电源外壳] [英] A cmdlet which returns multiple objects, what collection type is it, if any? [PowerShell]

查看:81
本文介绍了一个返回多个对象的cmdlet,它是什么集合类型(如果有)? [电源外壳]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Get-ADuser cmdlet的示例:

An example of the Get-ADuser cmdlet:

$Users = Get-ADuser -Filter *

在大多数情况下,它将返回多个ADuser对象,但是它是什么集合"类型? 该文档仅说它将返回Microsoft.ActiveDirectory.Management.ADUser的一个或多个用户对象.

It will in most cases return multiple ADuser objects, but what "collection" type is it? The documentation only says it will returns one or more user objects of Microsoft.ActiveDirectory.Management.ADUser.

尝试使用例如($Users -is [System.Collections.ArrayList])但我无法确定收藏"类型吗?

Tried to use e.g. ($Users -is [System.Collections.ArrayList]) but I cannot nail the "collection" type?

推荐答案

Cmdlet 自身通常在其输出中使用 no 收集类型. [1] :
它们向管道发出单个对象,这些对象可以表示:0(无),1或多个.

Cmdlets themselves typically use no collection type in their output.[1]:
They emit individual objects to the pipeline, which can situationally mean: 0 (none), 1, or multiple ones.

这正是Get-ADUser的作用:输出对象的具体数量取决于给定的参数;这就是为什么仅 Get-AdUser帮助主题的原因提到标量类型 ADUser 输出类型并声明其返回一个或多个".其中

This is precisely what Get-ADUser does: the specific number of output objects depends on the arguments that were given; that is why the Get-AdUser help topic only mentions scalar type ADUser as the output type and states that it "returns one or more" of them.

通常,PowerShell管道应是对象流,其特定长度(对象计数)不需要事先知道,并在后续管道段中添加命令在收到前一个段的输出对象 时对其进行处理(请参阅

Generally, the PowerShell pipeline is meant to be a stream of objects whose particular length (object count) need not be known in advance, with commands in subsequent pipeline segments processing the previous segment's output objects one by one, as they're being received (see about_Pipelines).

但是, PowerShell 引擎会自动在[object[]]数组中为您收集多个输出 [2] (如果需要) ,特别是如果您通过变量赋值捕获输出或通过(...)使用命令调用,则子表达式运算符 [3] ),作为表达式:

However, it is the PowerShell engine that automatically collects multiple outputs for you in an [object[]] array[2] if needed, notably if you capture output via a variable assignment or use a command call via (...), the grouping operator (or $(...), the subexpression operator[3]), as an expression:

# 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[]


但是,如果给定命令(可能是情境)仅输出一个单个对象,那么您将得到该对象本身 -包裹在一个数组中:


However, if a given command - possibly situationally - only outputs a single object, you'll then get just that object itself - it is not wrapped in an array:

# 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 can get tricky is that a given command can situationally produce either one or multiple outputs, depending on inputs and runtime conditions, so the engine may return either a single object or an array.

# !! 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.)

@()

@(), the array-subexpression operator, is designed to eliminate this ambiguity, if needed: By wrapping a command in @(...), PowerShell ensures that its output is always collected as [object[]] - even if the command happens to produce just one output object or even none:

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

对于变量分配,一种可能更有效的替代方法是使用[array] 类型约束 以确保输出变为数组:

With variable assignments, a potentially more efficient alternative is to use an [array] type constraint to ensure that the output becomes an array:

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

注意:

  • 这可能会更有效,因为如果RHS已经恰好是一个数组,则按原样分配它,而@(...)实际上枚举来自...和然后元素重新组合成一个 new ([object[]])数组.

  • This is potentially more efficient in that if the RHS already happens to be an array, it is assigned as-is, whereas @(...) actually enumerates the output from ... and then reassembles the elements into a new ([object[]]) array.

  • [array] 通过简单地传递保留输入数组的特定类型(例如,[array] $var = [int[]] (1..3)[int[]]数组按原样存储在$var).
  • [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]"cast"到$var = ... left 的位置-这就是使它成为变量的 type约束的原因-意味着变量的类型已被锁定,并在以后为$var分配不同的值将继续将RHS值转换为[array]([object[]])(除非您分配$null或"nothing"(请参阅​​下文))./p>

Placing the [array] "cast" to the left of $var = ... - which is what it makes it a type constraint on the variable - means that the type of the variable is locked in, and assigning different values to $var later will continue to convert the RHS value to [array] ([object[]]), if needed (unless you assign $null or "nothing" (see below)).

如果命令没有产生 no 输出,您将得到"nothing" (严格来说:

If a command produces no output, you'll get "nothing" (strictly speaking: the [System.Management.Automation.Internal.AutomationNull]::Value singleton), which in most cases behaves like $null[4]:

# 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]可以将整个集合作为一个整体输出 到管道中(在带有Write-Output -NoEnumerate $collection的PowerShell代码中,或更简洁地说,, $collection),但那只是管道中的另一个对象,恰好是集合本身.从整体上输出集合是一个异常,但是,这会改变通过管道传送的命令查看输出的方式,这可能是意外的.一个显着的例子是 ConvertFrom-Json在v7.0之前的意外行为.


[1] It is possible to output entire collections as a whole to the pipeline (in PowerShell code with Write-Output -NoEnumerate $collection or, more succinctly, , $collection), but that is then just another object in the pipeline that happens to be a collection itself. Outputting collections as a whole is an anomaly, however, that changes how commands you pipe to see the output, which can be unexpected; a prominent example is ConvertFrom-Jsons unexpected behavior prior to v7.0.

[2]一个 System.Array 元素类型为 System.Object 的实例,允许您可以在单个数组中混合不同类型的对象.

[2] a System.Array instance whose elements are of type System.Object, allowing you to mix objects of different types in a single array.

[3]通常使用(...)就足够了; $(...)仅在字符串插值(可扩展字符串)以及将整个语句或多个命令嵌入较大的表达式中时才需要;请注意,与单独的(...)不同,$(...)会打开单个元素数组的包装.比较(, 1).GetType().Name$(, 1).GetType().Name;参见此答案.

[3] Use of (...) is usually sufficient; $(...) is only needed for string interpolation (expandable strings) and for embedding whole statements or multiple commands in a larger expression; note that $(...), unlike (...) by itself, unwraps single-element arrays; compare (, 1).GetType().Name to $(, 1).GetType().Name; see this answer.

[4]在某些情况下,不"行为与$null有所不同,特别是在管道和switch语句中,如-is [AutomationNull]支持为 测试.

[4] There are scenarios in which "nothing" behaves differently from $null, notably in the pipeline and in switch statements, as detailed in this comment on GitHub; the linked issue is a feature request to make "nothing" more easily distinguishable from $null, by supporting -is [AutomationNull] as a test.

这篇关于一个返回多个对象的cmdlet,它是什么集合类型(如果有)? [电源外壳]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆