Search code examples
arrayspowershellhashvmwarepowercli

Error converting object array to hashtable


Quick Overview: Script has two functions, one gets a two lists of roles and puts them in a hash table, then returns that hash table. Process-Roles then accepts a hash table, and does some comparisons on it.

$RoleTable is supposed to be a hash table, but I think after my Get-Roles function, Powershell makes the $RoleTable an object array. I then get a conversion error:

Cannot convert the "System.Object[]" value of type "System.Object[]" to type 
"System.Collections.Hashtable".

Here's the "main" of my script

$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

Here's the function I make a hashtable in, and pass that to $RoleTable

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 | out-null
    $DiscoveredRoles["MasterRoles"] = Get-VIRole
    Disconnect-VIServer $MasterServer -Confirm:$false

    #Get Slave Roles
    Connect-VIServer $SlaveServer -Credential $Credential | out-null
    $DiscoveredRoles["SlaveRoles"] = Get-VIrole
    Disconnect-VIServer $SlaveServer -Confirm:$false

    Write-Verbose "`n + Retrieved Roles Successfully"

    return $DiscoveredRoles

}    

Here's where the error occurs. Process-Roles requires a hashtable, but I believe powershell converted $RoleTable to an array? (that's at least what my google-fu told me)

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-Verbose "$_ doesn't exist on slave"    
    }

    $SlaveRoleNames |Where-Object { $MasterRoleNames -notcontains $_ } |ForEach-Object {
        Write-Verbose "$_ doesn't exist on Master"    
    }

    Write-Verbose "`n + Processed Roles Successfully"
}

Solution

  • A PowerShell function returns an array when there are multiple values returned. Every statement in a function that returns a value that is not ignored and not assigned to a variable contributes to the return values.

    I see that Connect-VIServer returns something. Therefore the Get-Roles will return multiple values: including two from the two calls to Connect-VIServer.

    If you do not want the values from these other statements you need to explicitly get rid of them. Eg. by piping into out-null.

    Eg. (thank's to @MathiasRJessen):

    Connect-VIServer $SlaveServer -Credential $Credential | Out-Null