Copying PowerShell object


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:

2017-01-24-08_26_03-clipboard

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.

2017-01-24 08_41_04-Clipboard.png

I Hope this helps someone.

Until then

Keep Scripting

thom

One thought on “Copying PowerShell object

Leave a comment