Home > OS >  Powershell create New-Variable from foreach loop to be used outside of the loop
Powershell create New-Variable from foreach loop to be used outside of the loop

Time:07-20

So I am pulling in an array and then cleaning it to just the unique values I need and then running that though a foreach loop to create

$ZoneArray = Import-Csv -Path "Test.csv" | select Zone
$Zones = @()
foreach ($Zone in $ZoneArray){
        $Zones  = $Zone.Zone
}
$Zones = $Zones | select -Unique

foreach ($ZonesTest in $Zones){
            Set-Variable -Name "Zone$_" -Value $ZonesTest -Force
    
            New-UDTab -Text $ZonesTest -Content {
                    New-Variable -Name 'CurrentZone'
                    New-UDmuButton -Id 'Zone1Test' -Text (   " On") -Variant contained -FullWidth -OnClick {
                            Show-UDToast -Message "Starting" -Duration 1000 -Position center
                            $ZoneFullArray = $FullArray | Where-Object Zone -eq $ZonesTest
                            foreach ($ZoneFullArrayTest in $ZoneFullArray){
                                    Set-UDButtonStateChange -Id 'Zone1Test' -Text $ZoneFullArrayTest.ReceiverIPAddress
                                    Start-Sleep -Milliseconds 1000
                            }
                    }
            }
    }

Using Set-Variable -Name "Zone$_" -Value $ZonesTest -Force I am able to call the correct value while it is running. I have tried using

$Q=1
Set-Variable -Name "Zone$Q" -Value $ZonesTest -Force`
$Q  

But then I don't know how to dynamically call back the correct $Zone$Q for the later button press.

Is there anyway to program a dynamic variable that remembers the state it was made and then I can recall it later without knowing it's name? I know that sounds really confusing.

Ideas?


Edit:

I am banging my head against the wall. I know that the $ZoneFullArray = ... and foreach ($ZoneFullArrayTest in $ZoneFullArray){... is what is breaking it but can't think of another way to write it. The problem I am trying to solve with the second foreach to create a button dynamically based off the CSV table and then pull the value of the IP addresses that match the main row value making $Zones. The issue is that the code within the button is not run until it is pressed so it is hard to write them dynamically.

CodePudding user response:

As iRon points out, variable indirection (referring to variables indirectly, via dynamically created variable names) is best avoided - see this post.

It sounds like what you're really looking for are script-block closures that lock in then-current variable values in each iteration of a loop, along the following lines:

# Sample input zones.
$zones = 'foo', 'bar', 'baz'

# Create a script block with a closure for each zone.
$scriptBlocks = 
 foreach ($zone in $zones) {
   # .GetNewClosure() locks in the iteration-specific value of $zone
   { "This zone: $zone" }.GetNewClosure()
 } 

# Execute the script blocks to demonstrate that the values where
# captured as intended.
$scriptBlocks | ForEach-Object { & $_ }

Output:

This zone: foo
This zone: bar
This zone: baz

CodePudding user response:

So I ended up using the code blocks @mklement0 suggested but added the param option I found to pass data into the code block.

$CodeBlock = { param($par1, $par2)
foreach ($Row in $par1){
        $SwitchIPCurrent = $Row.SwitchIP
        $SwitchUsernameCurrent = $Row.SwitchUsername
        $SwitchPasswordCurrent = $Row.SwitchPassword
        $SwitchPortCurrent = $Row.SwitchPort
}
}

To run the code just pass the param into the code block

&$CodeBlock -par1 $ImportedArray -par2 $Variable
  • Related