VMware Cloud Community
zenivox
Hot Shot
Hot Shot
Jump to solution

function to parse and return array items does not list item names

Hello there, I wrote a function that parse arrays content and returns list of items plus an item property. If I execute the single lines of the function I get the expected result, which is this:

zenivox_0-1610116917600.png

while if I use the function in a script I only get the item property but not its name:

zenivox_1-1610116976415.png

and here is the function I created:

function Get-ArrayContent {
    param (
        [Array[]]$array,
        [string]$message,
        [string]$destinationType
    )
    $i = 1
    Write-Host $message -ForegroundColor Yellow 
    Write-Host "." -ForegroundColor Yellow
    switch ($destinationType){
        "datastore" {
            $Datastores = $Array | Select-Object Name,@{N="Free Space %";E={[math]::Round(($_.FreeSpaceGB)/($_.CapacityGB)*100,2)}} | Sort-Object FreeSpaceGB -Descending
            $Datastores | ForEach-Object{ Write-Host $i":" ($_.Name) -ForegroundColor White -NoNewline; Write-Host $_."Free Space %" "% Free" -ForegroundColor Yellow; $i++} 
        }
        "ADGroup" { 'do something else'}
        default { $Array | ForEach-Object{Write-Host $i":" $_.Name; $i++} }
    }
    Write-Host "." -ForegroundColor Green
    $DSIndex = Read-Host "Enter a number ( 1 -" $Array.count ")"
    $obj = $Array[$DSIndex - 1].Name
    Write-Host "You have selected the $obj $destinationType" -ForegroundColor Green 
    Write-Host "." -ForegroundColor Green
    Set-Variable -Name $destinationType -Scope Global -Value $obj
    Start-Sleep -Seconds 2
}

and here the lines where I use the function in the script:

# Choose a Datastore to deploy to
$vmhost = Get-Cluster $Cluster | Get-VMHost | Select-Object -First 1
Get-ArrayContent -array (Get-VMHost $vmhost | Get-Datastore ) -destinationType "datastore" -message "Select onto which datastore to place $computer"
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

There are a couple of issues.

You are passing an Array, but your parameter definition says that you are passing an array of arrays.

[Array[]]$array,

Which is the reason why the Name property is not found.

You sort on a property (FreeSpaceGB) that is not on the object.
The object at that point in the pipeline only has the properties Name and 'FreeSpace %'

            $Datastores = $Array | Select-Object Name,
                @{N="Free Space %";E={[math]::Round(($_.FreeSpaceGB)/($_.CapacityGB)*100,2)}} | 
                Sort-Object FreeSpaceGB -Descending

  
What are you trying to with defining a variable with the same name as a parameter to your function?

Set-Variable -Name $destinationType -Scope Global -Value $obj

 

  The following should do what you want it to do

function Get-ArrayContent {
    param (
        [PSObject[]]$array,
        [string]$message,
        [string]$destinationType
    )
    $i = 1
    Write-Host $message -ForegroundColor Yellow 
    Write-Host "." -ForegroundColor Yellow
    switch ($destinationType){
        "datastore" {
            $Datastores = $Array | Select-Object Name,
                @{N="Free Space %";E={[math]::Round(($_.FreeSpaceGB)/($_.CapacityGB)*100,2)}} | 
                Sort-Object "Free Space %" -Descending
            $Datastores | ForEach-Object{ 
                Write-Host "$($i): $($_.Name) " -ForegroundColor White -NoNewline
                Write-Host "$($_."Free Space %") % Free" -ForegroundColor Yellow
                $i++
            } 
        }
        "ADGroup" { 'do something else'}
        default { $Array | ForEach-Object{Write-Host $i":" $_.Name; $i++} }
    }
    Write-Host "." -ForegroundColor Green
    $DSIndex = Read-Host "Enter a number ( 1 -" $Array.count ")"
    $obj = $Array[$DSIndex - 1].Name
    Write-Host "You have selected the $obj $destinationType" -ForegroundColor Green 
    Write-Host "." -ForegroundColor Green
#    Set-Variable -Name $destinationType -Scope Global -Value $obj
    Start-Sleep -Seconds 2
}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
4 Replies
LucD
Leadership
Leadership
Jump to solution

There are a couple of issues.

You are passing an Array, but your parameter definition says that you are passing an array of arrays.

[Array[]]$array,

Which is the reason why the Name property is not found.

You sort on a property (FreeSpaceGB) that is not on the object.
The object at that point in the pipeline only has the properties Name and 'FreeSpace %'

            $Datastores = $Array | Select-Object Name,
                @{N="Free Space %";E={[math]::Round(($_.FreeSpaceGB)/($_.CapacityGB)*100,2)}} | 
                Sort-Object FreeSpaceGB -Descending

  
What are you trying to with defining a variable with the same name as a parameter to your function?

Set-Variable -Name $destinationType -Scope Global -Value $obj

 

  The following should do what you want it to do

function Get-ArrayContent {
    param (
        [PSObject[]]$array,
        [string]$message,
        [string]$destinationType
    )
    $i = 1
    Write-Host $message -ForegroundColor Yellow 
    Write-Host "." -ForegroundColor Yellow
    switch ($destinationType){
        "datastore" {
            $Datastores = $Array | Select-Object Name,
                @{N="Free Space %";E={[math]::Round(($_.FreeSpaceGB)/($_.CapacityGB)*100,2)}} | 
                Sort-Object "Free Space %" -Descending
            $Datastores | ForEach-Object{ 
                Write-Host "$($i): $($_.Name) " -ForegroundColor White -NoNewline
                Write-Host "$($_."Free Space %") % Free" -ForegroundColor Yellow
                $i++
            } 
        }
        "ADGroup" { 'do something else'}
        default { $Array | ForEach-Object{Write-Host $i":" $_.Name; $i++} }
    }
    Write-Host "." -ForegroundColor Green
    $DSIndex = Read-Host "Enter a number ( 1 -" $Array.count ")"
    $obj = $Array[$DSIndex - 1].Name
    Write-Host "You have selected the $obj $destinationType" -ForegroundColor Green 
    Write-Host "." -ForegroundColor Green
#    Set-Variable -Name $destinationType -Scope Global -Value $obj
    Start-Sleep -Seconds 2
}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

Many thanks Luc! I misunderstood the syntax for declaring the array parameters... obviously now it works!

This part:

 $obj = $Array[$DSIndex - 1].Name
    Write-Host "You have selected the $obj $destinationType" -ForegroundColor Green 
    Write-Host "." -ForegroundColor Green
    Set-Variable -Name $destinationType -Scope Global -Value $obj

prepares the variable that will be used later for this below:

New-VM -Name $computer -VMHost $vmhost -Datastore $Datastore -Location (Get-Folder $FOLDER -location $vDC) -ErrorAction Stop

 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

I would return the selected object via a return, which you can then assign in the calling code to a variable.
Using variables in the Global scope to exchange data between caller and function can be tricky (and hard to debug)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
zenivox
Hot Shot
Hot Shot
Jump to solution

thanks Luc I'll follow your advice! As I am planning to use it for multiple purpose I'll create a return variable into each switch case. Have a great weekend man!

0 Kudos