Dynamic Variables

This topic contains 10 replies, has 3 voices, and was last updated by Profile photo of Wayne Robinson Wayne Robinson 8 months, 3 weeks ago.

  • Author
    Posts
  • #36822
    Profile photo of Wayne Robinson
    Wayne Robinson
    Participant

    Hi everyone, I have a gap in my knowledge i am hoping someone can fill, here is my problem:
    I wish to dynamically query some info at runtime to then create a dynamic number of variables, which i then want to query also, the code i have is below:
    `

    $AllNodes = Get-StorageNode
    $i=0
    Foreach ($Node in $AllNodes)
        {
            $i++
            New-Variable -Name $("Node$i`Disks") -Value (Get-PhysicalDisks)
            New-Variable -Name $("Node$i`Disksize") -Value 0
            $Temp = (Get-Variable -Name $("Node$i`Disks"))
            $TempSize = (GetVariable -Name $("Node$i`Disksize"))
                    Foreach ($item in $Temp)
                        {
                            $TempSize = $TempSize + $item.Value.Size
                        }
            $("Node$i`Disksize") = $TempSize              
        }
    

    `
    The error is on this line $("Node$i`Disksize") = $TempSize, it cannot assign the value in $TempSize to the variable, what is the correct way to do this?
    Regards
    Wayne

  • #36829
    Profile photo of Paal Braathen
    Paal Braathen
    Participant

    This?

    Set-Variable -Name $("Node$i`Disksize") -Value $TempSize
  • #36830
    Profile photo of Paal Braathen
    Paal Braathen
    Participant

    I guess what you're doing here

    $("Node$i`Disksize") = $TempSize 

    is trying to assign a variable to a string. That won't work.

  • #36832
    Profile photo of Wayne Robinson
    Wayne Robinson
    Participant

    Hi Paal,

    yes this looks like my problem, the $item.value.size variable doesnt have an op method. However i need to get all of those disk sizes and store them in a variable, still working on it, i will post back as soon as i find anything

  • #36833
    Profile photo of Wayne Robinson
    Wayne Robinson
    Participant

    I suppose then the only other way is if i can do:

    Foreach ($item in $("Node$i`Disks")) and loop through that, but i cant seem to get that to work either 🙁

  • #36839
    Profile photo of Wayne Robinson
    Wayne Robinson
    Participant

    Got it, it was simple..

    $AllNodes = Get-StorageNode
    $i=0
    Foreach ($Node in $AllNodes)
        {
            $i++
            New-Variable -Name $("Node$i`Disks") -Value (Get-PhysicalDisks)
            New-Variable -Name $("Node$i`Disksize") -Value 0
            $Temp = (Get-Variable -Name $("Node$i`Disks"))
                    Foreach ($item in $(get-variable -Name Node$i`Disks -ValueOnly))
                        {
                            [Int64]$TempSize = Get-variable -Name "Node$i`Disksize" -Valueonly
                            Set-Variable -Name "Node$i`Disksize" -Value ($TempSize + $item.size)
                        }         
        }
    

    Thanks for the input Paal 🙂

  • #36840
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Personally, I'd say any time you're trying to dynamically create variable names like this, what you really want is a collection of some sort. Maybe an array, maybe a dictionary, whatever makes more sense at the time. For example:

    $hash = @{}
    
    $AllNodes = Get-StorageNode
    $i=0
    Foreach ($Node in $AllNodes)
        {
            $i++
            $hash[$i] = @{
                Disks = Get-PhysicalDisks
                DiskSize = 0
            }
                    Foreach ($item in $hash[$i].Disks)
                        {
                            $hash[$i].DiskSize += $item.Size
                        }
        }
    
  • #36841
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Incidentally, every single $i in that hashtable should wind up with identical data. You're looping over the $AllNodes array, but not using $Node anywhere inside the loop (such as in the call to Get-PhysicalDisks.)

  • #36844
    Profile photo of Wayne Robinson
    Wayne Robinson
    Participant

    Interesting Dave, il look at the array / dictionary method thanks, and I wouldn't examine the code too carefully, it was changed to protect its identity lol, it was more the logic i was trying to understand 🙂

  • #36846
    Profile photo of Paal Braathen
    Paal Braathen
    Participant

    I'm not familiar with Get-StorageNode or the Get-PhysicalDisk, but I guess I would do something like

    $Nodes = Get-StorageNode
    
    $NodeSizes = @{}
    
    foreach ($Node in $Nodes) {
        $Disks = Get-PhysicalDisk -StorageNode $Node
        $SizeSum = $Disks | Measure-Object -Sum -Property "Size" | Select-Object -ExpandProperty "Sum"
        $NodeSizes[$Node.Name] = $SizeSum
    }

    Then the hashtable, $NodeSizes, will have the node name and total disk size as key-value pairs.

    I see that the size of the PhysicalDisk object is an uint64. Measure-Object converts this and gives the sum as a double. You probably don't need to worry about this, but keep the type in mind if you want to pass the value on 🙂

  • #36848
    Profile photo of Wayne Robinson
    Wayne Robinson
    Participant

    Cool thanks Paal, il look at this too, very helpful indeed 🙂

You must be logged in to reply to this topic.