My Get-AzureStorSimpleAccessControlRecord
call returns 2 objects, with
Name
property values servertest4
and servertest3
.
However,
Get-AzureStorSimpleAccessControlRecord | where {$_.Name -like '*servertest4*'}
is unexpectedly returning both objects.
If I pass it through a for-each loop, the where statement is working to capture that property.
Get-AzureStorSimpleAccessControlRecord | % {$_.Name} | where {$_ -like 'servertest4'}
servertest4
Passing the original command to Get-Member
unexpectedly doesn't show the Name
property. Is that the problem?
If so, why does it have it as a column and why does it work when I pass it through the for-each loop? This is all it returned for properties (I stripped the methods out):
Get-AzureStorSimpleAccessControlRecord | gm
TypeName: System.Collections.Generic.List`1[[Microsoft.WindowsAzure.Management.StorSimple.Models.AccessControlRecord, Microsoft.WindowsAzure.Management.StorSimple,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]
Name MemberType Definition
Item ParameterizedProperty
Microsoft.WindowsAzure.Management.StorSimple.Models.AccessControlRecord Item(int index) {get;set;}
Capacity Property int Capacity {get;set;}
Count Property int Count {get;}
IsFixedSize Property bool IsFixedSize {get;}
IsReadOnly Property bool IsReadOnly {get;}
IsSynchronized Property bool IsSynchronized {get;}
SyncRoot Property System.Object SyncRoot {get;}
What am I missing?
It seems that Get-AzureStorSimpleAccessControlRecord
is ill-behaved and sends its output collection as a whole through the pipeline , instead of item by item.
I've reported the issue here at windowsserver.uservoice.com , in case you want to vote to have it fixed.
You should be able work around that by enclosing the call in (...)
:
(Get-AzureStorSimpleAccessControlRecord) | Where-Object { $_.Name -like '*servertest4*' }
Enclosing in (...)
makes PS convert the collection to a regular PS array up front, whose elements are then sent through the pipeline as expected; for background information, see this answer of mine.
Note, however, that this workaround invariably collects all elements up front before sending the items through the pipeline one by one.
If you want to avoid that , you can insert dummy pipeline stage | ForEach-Object { $_ }
| ForEach-Object { $_ }
, which also forces item-by-item enumeration:
Get-AzureStorSimpleAccessControlRecord | ForEach-Object { $_ } |
Where-Object { $_.Name -like '*servertest4*' }
The following simplified example simulates Get-AzureStorSimpleAccessControlRecord
's undesired behavior by creating an [int[]]
array that is artificially wrapped in another array by way of the unary form of the array-construction operator, ,
.
Sending this wrapped collection through the pipeline causes it to be sent as a whole instead of item by item.
$wrappedColl = , [int[]] (1, 2) # create artificially wrapped collection
Now, Get-Member
reports the wrapped collection type instead of the type of the individual items, as normally happens (the pipeline unwrapped the outer array and sent its only element - the inner [int[]]
array - as-is):
> $wrappedColl | Get-Member
TypeName: System.Int32[] # !! Type of the wrapped array as a whole
...
The array being passed as a whole also gets in the way when applying a Where-Object
filter, which is what prompted the question:
# Trying to extract element 2 outputs the whole array(!).
> $wrappedColl | Where-Object { $_ -eq 2 }
1
2
Since the [int[]]
array is passed as a whole, that's what $_
is bound to inside the Where-Object
script block.
Applying -eq
to a LHS that is an array performs array filtering rather than returning a simple [bool]
value, so that [int[]] (1, 2) -eq 2
returns the array of matching items, which in this case is [object[]] 2
(note the result array is alway a regular PS array, of type [object[]]
).
The resulting (single-item) array is then interpreted as a Boolean in the context of the Where-Object
cmdlet, and any non-empty array evaluates to $true
when coerced to a Boolean.
Therefore, since the script block passed to Where-Object
evaluated to $true
, the input object is passed through , which in this case is, as stated, the whole [int[]]
array.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.