Array of objects questions

Hello,

This is my first time posting so apologies if I’m posting in the wrong place or using incorrect formatting.

I’m fairly new to Powershell and would appreciate a) Some advice on whether the approach I’m taking is sensible and b) if it is some help with a specific question.

Approach:

I have a situation where I want to:

Keep a SQL connection and a text variable related to each other
Have an array as follows:

Array item 1: Connection and text variable
Array item 2: Connection and text variable
e.t.c.

I think the best way to do that is to have an array of pscustomobjects where the PSCustomObject has one SQL connection property and one string property?

Specific question:

I think I almost have it working. In the example below I’ve swapped to strings so I can post a useable example.

[pscustomobject] $ServerRoles=@()

[pscustomobject]$ServerRole = @{
  Connection  = 1
  Code=“Test 1”}
$ServerRoles+=$ServerRole

[pscustomobject]$ServerRole = @{
  Connection  = 2
  Code=“Test 2”}

$ServerRoles+=$ServerRole

write-host $ServerRoles.Count
write-host $ServerRoles[1].code

[pscustomobject] $RoleCodes=@()
$RoleCodes=$ServerRoles | Where-Object {$_.Connection -eq 1}

$RoleCodes
write-host $RoleCodes.Count

$ServerRole is a PSCustomObject
$ServerRoles is an array of $ServerRole Objects

Those seem to work OK

The line that isn’t giving me the result I want is

$RoleCodes=$ServerRoles | Where-Object {$_.Connection -eq 1}

I want $RoleCode to contain the $ServerRole pscustomobject that matches the where clause.

However it looks to contain two separate entries one for $Serverrole.Connection and one for $Serverrole.Code.

In other words I think it’s split the $ServerRole pscustomObject into two array items rather that keep it as a pscustomobject.

Thanks

Hello and thanks for posting. Let’s get some formatting on that code before we go any further.

Would you mind editing your original post and using the Preformatted Text button to turn all of your shared code in to a code block? It’s usually under the plus button at the end of the formatting toolbar.

Guide to Posting Code - Redux

At first glance I’m onboard with your approach, but I don’t think you need to strongly type your arrays as [PSCustomObject], in fact that might cause problems so I would just leave your array declarations as $ServerRoles = @()

You could also avoid the extra work with += by declaring your PSCustomObjects inside your array declaration

$ServerRoles = @(
    [PSCustomObject]@{
        Connection = 1
        Code = "test"
    },
    [PSCustomObject]@{
        Connection = 2
        Code = "test2"
    }
)
2 Likes

Thank you for your reply and help.

Apologies, I misread the help guide and did the code formatting wrong. It should be correct now.

Thank you for your thoughts on my approach and the suggestions you’ve made.

Another note, array indexes start at 0 instead of 1, so if you’re looking for the first item in the array, it would be `$ServerRoles[0].code`

Not sure if that’s what you were going for or not, but didn’t want you to miss that detail :slight_smile:

Thanks for the advice.

I did know and should have made my example code clearer by using [0]. Apologies.

The following code copies the correct object from $ServerRoles but it seems to split it into two elements.

$RoleCodes=$ServerRoles | Where-Object {$_.Connection -eq 1}
write-host $RoleCodes.Count

Gives a value of 2 when I was expecting a value of 1 because I copied one object across.

You get a value of “2” because there are two properties in the PSCustomObject. You seem to be expecting $RoleCodes to be an array. But because there was only one object selected by the Where-Object the $RoleCodes type is PSCustomObject.
You can correct that by strongly typing $RoleCodes like this: [array]$RoleCodes=$ServerRoles | Where-Object {$_.Connection -eq 1}

This is close, but incorrect. It’s a hashtable, not a PSCustomObject. There are 2 entries in the hash table. A PSCustomObject can have 50 properties, but it would still be only one count. The OP is putting the cast to PSCustomObject in the wrong place.

[pscustomobject]$ServerRole = @{
    Connection  = 2
    Code=“Test 2”
}

$ServerRole | Get-Member

   TypeName: System.Collections.Hashtable

OP, simply move the PSCustomObject cast to the front

$ServerRole = [pscustomobject]@{
    Connection  = 2
    Code=“Test 2”
}

$ServerRole | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Then things will work closer to what you’re expecting.


$ServerRoleList = [pscustomobject]@{
    Connection = 1
    Code       = "Test 1"
},
[pscustomobject]@{
    Connection = 2
    Code       = "Test 2"
}

write-host $ServerRoleList.Count

$RoleCodes = $ServerRoleList | Where-Object {$_.Connection -eq 1}

Beware that a single item (scalar) doesn’t automatically have a count property like an array does. If you may end up with just a single item (or none) you can simply surround the variable with an array expression

write-host @($RoleCodes).Count

Or you can strongly type it like already suggested

[array]$RoleCodes = $ServerRoleList | Where-Object {$_.Connection -eq 1}

I would also beware of using single/plural variable names. It’s very easy to mix them up. That’s why I changed the one to $ServerRoleList. It’s a lot easier to spot the difference between $ServerRole and $ServerRoleList than it is $ServerRole vs $ServerRoles

1 Like

@krzydoug

This is close, but incorrect. It’s a hashtable, not a PSCustomObject.

You’re right. I was looking only at the lines:

[pscustomobject] $RoleCodes=@()
$RoleCodes=$ServerRoles | Where-Object {$_.Connection -eq 1}

All,

Apologies for taking a few days to reply. I had to sort out some other issues.

Thank you for your help. I haven’t had had chance to read through all the replies in detail but I will do in the next few days. I just wanted to write a quick reply to acknowledge the replies and the help contained in them.

Thanks

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.