Lately I’ve needed to take a PowerShell object and use it in several places in a JSON document that PowerShell nicely put in a custom object for me. What I needed this object to do was to allow for a set of each one of the properties and they needed to be different for each time I added it to the JSON object. To get this to work I tried several different means. This post is about how I worked to solve this issue.
First we’ll start with a customobject that comes from JSON
$tasks2add = $tasks = $null $taskjson = @' [ { "taskId": "1", "name": "Server-Scommaintenance", "enabled": false, "inputs": { "servers": "$(serverMonitors) ", "webMonitors": "$(webMonitors)", "MinuteValue": "2000", "maintValue": "inMaint" } }, { "taskId": "2", "name": "Server-Scommaintenance", "enabled": false, "inputs": { "servers": "$(serverMonitors) ", "webMonitors": "$(webMonitors)", "emailusers": "$(ScomNotify)", "MinuteValue": "2000", "maintValue": "RemoveMaint" } } ] '@ $tasks2add = $taskjson|convertfrom-json
Now if look at my variable $tasks2Add we’ll see that it has all the items in the custom json above:
$tasks2add = $taskjson|convertfrom-json PS PS:\> $tasks2add taskId name enabled inputs ------ ---- ------- ------ 1 Server-Scommaintenance False @{servers=$(serverMonitors) ; webMonitors=$(webMonitors); MinuteValue=2000; maintValue=inMaint} 2 Server-Scommaintenance False @{servers=$(serverMonitors) ; webMonitors=$(webMonitors); emailusers=$(ScomNotify); MinuteValue=2000; maintValue=RemoveMaint}
Now if I take that same set of objects and add it to another variable and then set each one. Lets see what the output looks like:
$newArraylist = new-object System.Collections.Generic.List[system.object] $newArraylist.Add((New-object pscustomobject ($tasks2add[0]))) $newArraylist.Add((New-object pscustomobject ($tasks2add[1]))) $newArraylist.Add((New-object pscustomobject ($tasks2add[0]))) $newArraylist.Add((New-object pscustomobject ($tasks2add[1]))) #$newArraylist.count $newArraylist[0].enabled = $true $newArraylist[1].enabled = $false $newArraylist[2].enabled = $false $newArraylist[3].enabled = $true $newArraylist
Here is what my output looks like:
You would expect that the first and second tasks would be set to $true and $false respectively as I set them with the $newArraylist[x].enabled = $true / $false.
So what happened here. PowerShell takes the array object and points (references) the values in the object to the first created object. So we aren’t really getting a copy we are getting a reference to the first created object. After much gnashing of teeth and trying several different methods I finally came to a solution that is described in this PowerShell QA post.
To get this to work in the fashion I wanted which is I want each one of the copy’s of the new object to be settable independently I had to use the psobject property of my custom object. I’ll do this with the method called copy on the psobject property.
$tasks2add[1].PSObject.copy()
This makes the code much shorter and solves my issue where I can now set my custom objects like I’d like them to be.
$newArraylist = new-object System.Collections.Generic.List[system.object] $newArraylist.Add($tasks2add[0].PSObject.Copy()) $newArraylist.Add($tasks2add[1].PSObject.Copy()) $newArraylist.Add($tasks2add[0].PSObject.Copy()) $newArraylist.Add($tasks2add[1].PSObject.Copy()) #$newArraylist.count $newArraylist[0].enabled = $true $newArraylist[1].enabled = $false $newArraylist[2].enabled = $false $newArraylist[3].enabled = $true $newArraylist
Now if I look at my object it is now in the condition I want where I can set each item I add to my array list.
I Hope this helps someone.
Until then
Keep Scripting
thom
Works man ! Thanks for this 😀 !
LikeLike