一个返回多个对象的cmdlet,它是什么集合类型(如果有)? [电源外壳] [英] A cmdlet which returns multiple objects, what collection type is it, if any? [PowerShell]
问题描述
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-Json
s 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屋!