我正在寻找一些帮助来解决将 .key 值与对象进行比较的问题。
基本上这里发生的事情是我连接到两个 VMware vCenter 并下载角色列表并将这些角色放入两个哈希表中,然后比较它们。
问题归结为 Process-Roles 函数,其中比较逻辑在某处存在缺陷。它输出两个列表中的所有角色。我认为 (-not .containskey) 不能正常工作。我已经在 powerGUI 中进行了调试,并且哈希表和 mstr_roles/slave_roles 都已正确填充。
角色列表应该是对象列表,因为它们填充了 Get-VIRole。
哈希表应该是object-in-key,value null 列表。这两个可以比较吗?我正在尝试检查角色列表中的 $role 对象是否存在于哈希表的 .key 值列表中。
$creds = Get-Credential
$mst = Read-Host "`n Master Server: "
$slv = Read-Host "`n Slave Server: "
$hsh_mstr_roles = @{}
$hsh_slave_roles = @{}
$mstr_roles = ""
$slave_roles = ""
Get-Roles -MasterServer $mst -SlaveServer $slv
Process-Roles
.
function Get-Roles() {
Param(
[Parameter(Mandatory=$True,Position=0)]
[string]$MasterServer,
[Parameter(Mandatory=$True,Position=1)]
[string]$SlaveServer
)
#Get Master Roles
Connect-VIServer $MasterServer -Credential $creds
$mstr_roles = Get-VIrole
foreach ($role in $mstr_roles) {
$hsh_mstr_roles.add($role, $null)
}
Disconnect-VIServer $MasterServer -Confirm:$false
#Get Slave Roles
Connect-VIServer $SlaveServer -Credential $creds
$slave_roles = Get-VIrole
foreach ($role in $slave_roles) {
$hsh_slave_roles.add($role, $null)
}
Disconnect-VIServer $SlaveServer -Confirm:$false
Write-Host "`n + Retrieved Roles Successfully"
}
.
function Process-Roles () {
#Get Roles on Master NOT ON SLAVE
Write-Host "`n"
foreach ($role in $mstr_roles){
if(-not $hsh_slave_roles.containsKey($role)){
Write-Host $role "doesn't exist on slave"
}
}
#Get Roles on Slave NOT ON MASTER
foreach ($role in $slave_roles){
if(-not $hsh_mstr_roles.containsKey($role)){
Write-Host $role "doesn't exist on master"
}
}
Write-Host "`n + Processed Roles Successfully"
}
最佳答案
最简单的方法是使用 -notcontains
找到每个哈希表具有的两组键之一的补充:
function Process-Roles {
param(
[hashtable]$MasterRoles,
[hashtable]$SlaveRoles
)
# Complement to slave roles (those ONLY in $MasterRoles)
$MasterRoles.Keys |Where-Object { $SlaveRoles -notcontains $_ }|ForEach-Object {
Write-Host "$_ not in Slave Roles"
}
# and the other way around (those ONLY in $SlaveRoles)
$SlaveRoles.Keys |Where-Object { $MasterRoles -notcontains $_ }|ForEach-Object {
Write-Host "$_ not in Master Roles"
}
}
我必须补充一点,您在不同范围内处理变量的方式是次优的。
Get-*
函数都应该) 我会选择这样的东西:
向
Credential
函数添加 Get-Roles
参数并返回结果,而不是修改父作用域中的变量(此处使用角色类别的 Hashtable):function Get-Roles {
Param(
[Parameter(Mandatory=$True,Position=0)]
[string]$MasterServer,
[Parameter(Mandatory=$True,Position=1)]
[string]$SlaveServer,
[Parameter(Mandatory=$True,Position=2)]
[pscredential]$Credential
)
$DiscoveredRoles = @{}
# Get Master Roles
Connect-VIServer $MasterServer -Credential $Credential
$DiscoveredRoles["MasterRoles"] = Get-VIRole
Disconnect-VIServer $MasterServer -Confirm:$false
#Get Slave Roles
Connect-VIServer $SlaveServer -Credential $Credential
$DiscoveredRoles["SlaveRoles"] = Get-VIrole
Disconnect-VIServer $SlaveServer -Confirm:$false
Write-Verbose "`n + Retrieved Roles Successfully"
return $DiscoveredRoles
}
为
Process-Roles
函数定义参数,匹配您希望从 Get-Roles
生成的哈希表,并对角色名称进行与上述相同的比较,只是这次我们直接从 Role 对象中获取它们:function Process-Roles {
param(
[Parameter(Mandatory=$true)]
[ValidateScript({ $_.ContainsKey("MasterRoles") -and $_.ContainsKey("SlaveRoles") })]
[hashtable]$RoleTable
)
$MasterRoleNames = $RoleTable["MasterRoles"] |Select-Object -ExpandProperty Name
$SlaveRoleNames = $RoleTable["SlaveRoles"] |Select-Object -ExpandProperty Name
$MasterRoleNames |Where-Object { $SlaveRoleNames -notcontains $_ } |ForEach-Object {
Write-Host "$_ doesn't exist on slave"
}
$SlaveRoleNames |Where-Object { $MasterRoleNames -notcontains $_ } |ForEach-Object {
Write-Host "$_ doesn't exist on Master"
}
Write-Host "`n + Processed Roles Successfully"
}
使用新参数更新您的执行脚本:
$creds = Get-Credential
$MasterServer = Read-Host "`n Master Server: "
$SlaveServer = Read-Host "`n Slave Server: "
$RoleTable = Get-Roles -MasterServer $MasterServer -SlaveServer $SlaveServer -Credential $creds
Process-Roles -RoleTable $RoleTable
下一步是向
Process-Roles
函数添加管道支持,将 Write-Host
语句转换为 Write-Verbose
并添加错误处理,但我会将其作为练习留给 OP :-)关于powershell - 对象到哈希表键比较,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31810803/