问题
I have an object array of roles I pulled from two vcenters.
I'm trying to make a formatted table that has 3 columns : roles, master, slave
There would be "exists" or "missing" in the latter two columns.
The problem I believe happening is when it finds that the role exists in the master, it somehow marks the slave column as "missing", even though I know it's there.
I'm only a few months into Powershell, can anyone see anything wrong with my logic?
edit: RoleTable.AllRoles, RoleTable.MasterRoles, and RoleTable.SlaveRoles are all object arrays
$RoleTable.AllRoles | Select-Object Name,
@{Name = "Master Server"; Expression = {if ($RoleTable.MasterRoles -contains $_) {"EXISTS"} else {"MISSING"}}},
@{Name = "Slave Server"; Expression = {if ($RoleTable.SlaveRoles -contains $_) {"EXISTS"} else {"MISSING"}}}
Example of Roletable.Allroles object:
$RoleTable.AllRoles[1] | Select-Object *
Description : Not logged-in user (cannot be granted)
IsSystem : True
PrivilegeList : {System.Anonymous}
ServerId : /VIServer=someuser@xxxx-xxxx:443/
Server :
Id : -4
Name : Anonymous
Uid : /VIServer=someuser@xxxx-xxxx:Role=-4/
ExtensionData : VMware.Vim.AuthorizationRole
Client : VMware.VimAutomation.ViCore.Impl.V1.VimClient
回答1:
Unless $RoleTable.AllRoles[1] and an item in $RoleTable.SlaveRoles refer to the exact same object in memory, -contains will return $false, even if a seemingly identical object exists in $RoleTable.SlaveRoles.
(this is only true for reference types, not value types)
This should illustrate the difference:
Reference to same object:
PS C:\> $Collection = @(New-Object psobject -Property @{p=123})
PS C:\> $Item = $Collection[0]
PS C:\> $Collection -contains $Item
True
Reference to identical object:
PS C:\> $Collection = @(New-Object psobject -Property @{p=123})
PS C:\> $Item = New-Object psobject -Property @{p=123}
PS C:\> $Collection -contains $Item
False
In your example, you could use the Name or role Id property (as suggested by @jisaak):
$RoleTable.AllRoles | Select-Object Name,
@{Name = "OnMaster"; Expression = {$RoleTable.MasterRoles.Id -contains $_.Id}},
@{Name = "OnSlave"; Expression = {$RoleTable.SlaveRoles.Id -contains $_.Id}}
As shown above, I would probably use generic boolean values as indicators, rather than strings
This behaviour is a deliberate performance optimization in .NET - you never know how deep down the rabbit hole you would need to go to ensure exact value comparison of all internal attributes of an object.
Value types, on the other hand, are easier to perform equality comparisons against (and also don't necessarily have a memory reference to compare), resulting in:
[int]
PS C:\> $Collection = @(283)
PS C:\> $Item = $Collection[0]
PS C:\> $Collection -contains $Item
True
PS C:\> $Item = 283
PS C:\> $Collection -contains $Item
True
[string]:
PS C:\> $Collection = @("SomeString")
PS C:\> $Item = $Collection[0]
PS C:\> $Collection -contains $Item
True
PS C:\> $Item = "SomeString"
PS C:\> $Collection -contains $Item
True
and so on...
来源:https://stackoverflow.com/questions/31857138/object-array-comparison-with-custom-headers