Reputation: 1208
I'm sure that title isn't very clear, and for that I apologize. I've run into a bit of an issue with a script that I'm writing and am hoping for some assistance figuring out what is going on. I figured out how to resolve the issue, I'm more looking for why this is happening. The script is over 3k lines long, but the snippet I wrote below reproduces the same issue.
I have three hash tables, DeviceList, AllDevices and RemovedDevices. Devicelist is laid out explicitly, and AllDevices equals DeviceList. Within a loop, items that exist in RemovedDevices are removed from DeviceList. Even though AllDevices is only modified at the beginning in this sample, the devices are still being removed from it.
$DeviceList = @{"server1" = "email1"; "server2" = "email2"; "server3" = "email3"}
$AllDevices = $DeviceList
$RemovedDevices = @{"server1" = "email1"; "server2" = "email2"}
foreach($RemovedDevice in $RemovedDevices.GetEnumerator())
{
$DeviceList | where {$_.ContainsKey($RemovedDevice.Key)} | % {$_.Remove($RemovedDevice.Key)}
}
$AllDevices
Running the above text, $AllDevices is modified to only contain the server3 info, where it should still contain all 3 servers.
If I modify the second line to:
$AllDevices += $DeviceList
Then AllDevices maintains all 3 values. Using breakpoints and stepping through on the first version, I have verified that AllDevices is not being hit after the first time.
My overall question is: Why is AllDevices being modified to equal DeviceList after the loop has finished? If it's only called once at the beginning, shouldn't it's value remain static despite modifications to DeviceList? Rebuilding an array using a similar method doesn't overwrite AllDevices so I imagine it's a hashtable quirk.
PSVersion 5.0.10586.117
Upvotes: 2
Views: 290
Reputation: 174575
Why is AllDevices being modified to equal DeviceList after the loop has finished?
Because $AllDevices
is just a reference to the same underlying object as $DeviceList
If it's only called once at the beginning, shouldn't it's value remain static despite modifications to DeviceList?
If $AllDevices
was an identical object, sure, but it is not just identical - it is the same object.
Fortunately, hashtables implement the ICloneable
interface, so for shallow hashtables, you can use the Clone()
method:
$DeviceList = @{"server1" = "email1"; "server2" = "email2"; "server3" = "email3"}
$AllDevices = $DeviceList.Clone()
$RemovedDevices = @{"server1" = "email1"; "server2" = "email2"}
foreach($RemovedDevice in $RemovedDevices.GetEnumerator())
{
if($DeviceList.ContainsKey($RemovedDevice.Key))
{
$DeviceList.Remove($RemovedDevice.Key)
}
}
$AllDevices
I found the usage of a hashtable with Where-Object
super unreadable (not to mention unnecessarily slow), but functionally the above is the same as your original foreach
loop body
Upvotes: 4