VMware Cloud Community
DZ1
Hot Shot
Hot Shot
Jump to solution

Object output is not what I expected.

I am rewriting a script, and I'm having some issues with the output, the partial script is below.

1. Function something {

2. $ESXiVersion = $AllESXiHost | Foreach { Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } } }
3. $ESXiModel = $AllESXiHost | group Model | Select @{ N='Server Model'; E={ $_.Name } }, Count
$ESXiInfo = New-Object -TypeName PSObject
$ESXiInfo | Add-Member -MemberType NoteProperty -Name ESXihostCount -Value ($AllESXiHost).count
7. $ESXiInfo | Add-Member -MemberType NoteProperty -Name ESXiVersion -Value $ESXiVersion
8. $ESXiInfo | Add-Member -MemberType NoteProperty -Name "Hardware Model" -Value $ESXiModel
Write $ESXiInfo | fl

}

I have been trying some things, so line 2 (goes to line 7) is an experiment, and does not output anything, but when I write it like line 3 (goes to line 8), I get the same results.

When I call the function, lines 2 (Line 7 output) and 3 (line 8 output) show information similar to

{@{Server Model=Server; Count=7}, @{Server Model=Proliant; Count=1}}

I'm guessing the output is a hashtable, but of course I want the "@{}" removed from the script, but I'm not sure how.  A collegue suggested I use a foreach, but I'm sure I did that incorrectly.  If I save, let's say line 3 as as below:

$iHost = Get-VMHost | group Model | Select @{ N='Server Model'; E={ $_.Name } }, Count then the output looks fine

I see that it's a GroupInfo object...ok, I may be going on and on for something simple.  How can I remove the {@{}} from my script, so it looks better during output?  Thanks in advance. 

0 Kudos
1 Solution

Accepted Solutions
Grzesiekk
Expert
Expert
Jump to solution

Hi DZ1,

  sorry for confusing you. Please forget about this getEnumerator(), you do not have to use it at all. It was my mistake. I don't know why but i thought it was a hashtable and in order to split big hashtable to single objects you use getenumerator.. I don't know what i was thinking then. sorry abou that one.

Your line

1.$ESXiVersion = $AllESXiHost | Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } }

is wrong i suppose. If you want to get the esxiVersion you should not query the 'name' property. Name is the name of your esxi host like, esx123.local.biz but it does not hold the version name. To obtain the esxi version you should use property called 'version' from the vmhost object.

I do not know what do you want to count by this line because :

$AllESXiHost | Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } }

first of all it will not count anything because your are invoking count() method on vmhost object which is not an array or something like that type, which you could count.

You have to remember that in your infrastructure there can be multiple versions. So you have to do as many counts as many versions esxi you have in your VC.

That's why i suggested putting as many version properties as they are.

So that MAIN BIG object for statistic will hold a property for counting version3, version4 and version5  for example. In order to count individual versions you have to divide your esxi boxes by those versions

So

$AllESXiHost | group-object -property

will group all esxi hosts by their version number, you should receive as many objects as there are versions

you should see something similar to this

Count Name
----- ----
    1 3.5.0
    2 4.0.0
    3 4.1.0

So we have identified 1 host with 3.5 version, 2 hosts with version 4, and 3 hosts with version 4.1

So it all depends now from how you would like to put this information inside your statistics gathering objects $esxiinfo

i have suggested to put 3 different properties, or to have 1 property that will hold an arry.

IF you want to have just simple text, and you do not want to calculate it later in any way, you can just make 1 string , and join those strings into 1 big one.

$versions = $AllESXiHost | Group-Object -Property Version|select Count,Name
$versions

                                                              Count Name
                                                              ----- ----
                                                                  3 4.0.0
                                                                  7 3.5.0
                                                                 6 4.1.0'

I do not know how many versions you will receive. But since you can have mulitple versions i assume you want to distinguish them.

So i thought you want know to add as many versions properties to the newly created object.

2. $ESXiInfo = New-Object -TypeName PSObject

This is ok

3. $ESXiInfo | Add-Member -MemberType NoteProperty -Name Version -Value  ($ESXiVersion | Group -Property Version).getEnumerator() | Select Count,  'vSphere Version' 0

We will add properties to ESXiInfo now, we will ADD AS MANY PROPERTIES AS NEEDED.

so we need to add 3 properties

property Version4.0.0,

property Version4.10.0,

property Version3.5.0

So instead of line line we should use

$versionss| % {Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "Version$($_.Name)" -Value $_.Count}

For each version we have found , we will add new member to our $ESXiInfo object. This command will add automatically as many versions as they are.

Your ESXiInfo object will now have new properties

#23:01:55> $ESXiInfo|gm


   TypeName: System.Management.Automation.PSCustomObject

Name         MemberType   Definition
----         ----------   ----------
Equals       Method       bool Equals(System.Object obj)
GetHashCode  Method       int GetHashCode()
GetType      Method       type GetType()
ToString     Method       string ToString()
Version3.5.0 NoteProperty System.Int32 Version3.5.0=7
Version4.0.0 NoteProperty System.Int32 Version4.0.0=3
Version4.1.0 NoteProperty System.Int32 Version4.1.0=2

So you can get them

#23:02:55> $ESXiInfo.'Version3.5.0'
7

I think i have explained your 3 lines.

Now if you really want to have only 1 additional property for the versions, you can do it like this.

line 1

$AllESXiHost |Group-Object -Property Version |select count,name|%{[array]$versionss2+="Version $($_.Name) = $($_.Count)"}

This line will create variable $versionss2 , which will be used for holding informations about esxi versions.

Lets first get the versions and their count but store this information into simple array.

i#23:05:20> $versionss2
Version 4.0.0 = 3
Version 3.5.0 = 7
Version 4.1.0 = 2

Ok, we have 3 rows in our array, but you want to have 1 single property for versions so we will just join those lines.

So we are invoking add-member only ONCE this time:

Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "Esxi versions" -Value [string]::join(',',$versionss2)

We are joinng all elemnts from our array with versions with comma.

Take a look how your object will look now:

#23:10:55> $ESXiInfo | ft -AutoSize

Version4.0.0 Version3.5.0 Version4.1.0 Esxi versions
------------ ------------ ------------ -------------
           3            7          122 Version 4.0.0 = 3,Version 3.5.0 = 7,Version 4.1.0 = 2

first 3 colums were from the first method, fourth colum is the new approach. So if we would not even include the old approach it would look like this

Esxi versions
  -------------
Version 4.0.0 = 3,Version 3.5.0 = 7,Version 4.1.0 = 2

And for model you do exactly the same , but instead of measuring version property, you should measure model.

I hope this is more clear.

Greg

--- @blog https://grzegorzkulikowski.info

View solution in original post

0 Kudos
5 Replies
Grzesiekk
Expert
Expert
Jump to solution

Hi there,

$hosts=get-vmhost

($hosts | Group-Object -Property Version).getEnumerator() |select Count,Name

Count Name
-----   ----
     1   4.0.0
     3   3.5.0
     4   4.1.0

So from there..

$ESXiInfo=new-object PSObject

($hosts | Group-Object -Property Version).getEnumerator() |select Count,Name | % {Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "Version $($_.Name)" -Value $_.Count}

so now:

$ESXiInfo

Version 4.0.0                            Version 3.5.0                     Version 4.1.0
-------------                                   -------------                            -------------
            3                                     7                                  2

or

$ESXiInfo | fl

Version 4.0.0 : 3
Version 3.5.0 : 7
Version 4.1.0 : 2

So having this in mind, if you like this idea you can go with the model

($hosts | Group-Object -Property Model).getEnumerator() |select Count,Name | % {Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "Model $($_.Name)" -Value $_.Count}

So our object

$ESXiInfo

Version 4.0.0            : 8
Version 3.5.0            : 4
Version 4.1.0            : 5
Model abc  : 8
Model yxz: 4
Model etc..: 5

Or i don't know maybe you want to put array in the object :

($hosts |Group-Object -Property Version |select count,name).getEnumerator()|%{[array]$verArray+="$($_.Count) = $($_.Name)"}

Add-member -InputObject $ESXiInfo -MemberType Noteproperty -Name "Versions2" -Value $verArray

So now we would have

$ESXiInfo

Version 4.0.0            : 3
Version 3.5.0            : 7
Version 4.1.0            : 2
Model A  : 2
Model B : 4

Versions2                : {3 = 4.0.0, 7 = 3.5.0, 2 = 4.1.0}

I do not know if you wanted to have this way or other approach. LEt me know.

Regards,

Greg

--- @blog https://grzegorzkulikowski.info
DZ1
Hot Shot
Hot Shot
Jump to solution

Thanks for the input, I have a question.  When I try a Get-Member on either Get-VMhost or on Get-VMhost | group Version, I don't see a method called GetEnumerator.  I did try it outside of the script I am writing, and I see that it leaves of naming the actual hosts, I'm just curious where the method is.

Also, I see what you wrote, but how can I incorporate that into what I'm doing?  You indicate to create a new object, but since I'm trying to add it to an existing object, I'm running into issues.

Since I have this:

$ClusterCount = ($AllCluster).count
$ESXiVersion = $AllESXiHost | Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } }
$ESXiModel = $AllESXiHost | group Model | Select @{ N='Server Model'; E={ $_.Name } }, Count
$ESXiInfo = New-Object -TypeName PSObject
$ESXiInfo | Add-Member -MemberType NoteProperty -Name ESXihostCount -Value ($AllESXiHost).count
$ESXiInfo | Add-Member -MemberType NoteProperty -Name Version -Value ($ESXiVersion | Group -Property Version).getEnumerator() | Select Count, 'vSphere Version'
$ESXiInfo | Add-Member -MemberType NoteProperty -Name "Hardware Model" -Value $ESXiModel

Since $ESXiInfo is creating a new object, I'm not sure how I go in and add what I need to do, here are the main 3 lines

1.$ESXiVersion = $AllESXiHost | Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } }

2. $ESXiInfo = New-Object -TypeName PSObject

3. $ESXiInfo | Add-Member -MemberType NoteProperty -Name Version -Value ($ESXiVersion | Group -Property Version).getEnumerator() | Select Count, 'vSphere Version' 0

Line 1 is the variables, so should Ieave off  the hash table, and select here?

Line 2 is creating the object, and I want to keep adding to it, so how can I bring int the group version here?

I incorporated what you wrote into line 3, but that didn't work.

Thanks again for your help.

0 Kudos
Grzesiekk
Expert
Expert
Jump to solution

Hi DZ1,

  sorry for confusing you. Please forget about this getEnumerator(), you do not have to use it at all. It was my mistake. I don't know why but i thought it was a hashtable and in order to split big hashtable to single objects you use getenumerator.. I don't know what i was thinking then. sorry abou that one.

Your line

1.$ESXiVersion = $AllESXiHost | Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } }

is wrong i suppose. If you want to get the esxiVersion you should not query the 'name' property. Name is the name of your esxi host like, esx123.local.biz but it does not hold the version name. To obtain the esxi version you should use property called 'version' from the vmhost object.

I do not know what do you want to count by this line because :

$AllESXiHost | Select @{ N='vSphere Version'; E={ $_.Name } }, @{ N='Count'; E={ $_.Count } }

first of all it will not count anything because your are invoking count() method on vmhost object which is not an array or something like that type, which you could count.

You have to remember that in your infrastructure there can be multiple versions. So you have to do as many counts as many versions esxi you have in your VC.

That's why i suggested putting as many version properties as they are.

So that MAIN BIG object for statistic will hold a property for counting version3, version4 and version5  for example. In order to count individual versions you have to divide your esxi boxes by those versions

So

$AllESXiHost | group-object -property

will group all esxi hosts by their version number, you should receive as many objects as there are versions

you should see something similar to this

Count Name
----- ----
    1 3.5.0
    2 4.0.0
    3 4.1.0

So we have identified 1 host with 3.5 version, 2 hosts with version 4, and 3 hosts with version 4.1

So it all depends now from how you would like to put this information inside your statistics gathering objects $esxiinfo

i have suggested to put 3 different properties, or to have 1 property that will hold an arry.

IF you want to have just simple text, and you do not want to calculate it later in any way, you can just make 1 string , and join those strings into 1 big one.

$versions = $AllESXiHost | Group-Object -Property Version|select Count,Name
$versions

                                                              Count Name
                                                              ----- ----
                                                                  3 4.0.0
                                                                  7 3.5.0
                                                                 6 4.1.0'

I do not know how many versions you will receive. But since you can have mulitple versions i assume you want to distinguish them.

So i thought you want know to add as many versions properties to the newly created object.

2. $ESXiInfo = New-Object -TypeName PSObject

This is ok

3. $ESXiInfo | Add-Member -MemberType NoteProperty -Name Version -Value  ($ESXiVersion | Group -Property Version).getEnumerator() | Select Count,  'vSphere Version' 0

We will add properties to ESXiInfo now, we will ADD AS MANY PROPERTIES AS NEEDED.

so we need to add 3 properties

property Version4.0.0,

property Version4.10.0,

property Version3.5.0

So instead of line line we should use

$versionss| % {Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "Version$($_.Name)" -Value $_.Count}

For each version we have found , we will add new member to our $ESXiInfo object. This command will add automatically as many versions as they are.

Your ESXiInfo object will now have new properties

#23:01:55> $ESXiInfo|gm


   TypeName: System.Management.Automation.PSCustomObject

Name         MemberType   Definition
----         ----------   ----------
Equals       Method       bool Equals(System.Object obj)
GetHashCode  Method       int GetHashCode()
GetType      Method       type GetType()
ToString     Method       string ToString()
Version3.5.0 NoteProperty System.Int32 Version3.5.0=7
Version4.0.0 NoteProperty System.Int32 Version4.0.0=3
Version4.1.0 NoteProperty System.Int32 Version4.1.0=2

So you can get them

#23:02:55> $ESXiInfo.'Version3.5.0'
7

I think i have explained your 3 lines.

Now if you really want to have only 1 additional property for the versions, you can do it like this.

line 1

$AllESXiHost |Group-Object -Property Version |select count,name|%{[array]$versionss2+="Version $($_.Name) = $($_.Count)"}

This line will create variable $versionss2 , which will be used for holding informations about esxi versions.

Lets first get the versions and their count but store this information into simple array.

i#23:05:20> $versionss2
Version 4.0.0 = 3
Version 3.5.0 = 7
Version 4.1.0 = 2

Ok, we have 3 rows in our array, but you want to have 1 single property for versions so we will just join those lines.

So we are invoking add-member only ONCE this time:

Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "Esxi versions" -Value [string]::join(',',$versionss2)

We are joinng all elemnts from our array with versions with comma.

Take a look how your object will look now:

#23:10:55> $ESXiInfo | ft -AutoSize

Version4.0.0 Version3.5.0 Version4.1.0 Esxi versions
------------ ------------ ------------ -------------
           3            7          122 Version 4.0.0 = 3,Version 3.5.0 = 7,Version 4.1.0 = 2

first 3 colums were from the first method, fourth colum is the new approach. So if we would not even include the old approach it would look like this

Esxi versions
  -------------
Version 4.0.0 = 3,Version 3.5.0 = 7,Version 4.1.0 = 2

And for model you do exactly the same , but instead of measuring version property, you should measure model.

I hope this is more clear.

Greg

--- @blog https://grzegorzkulikowski.info
0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

I have not fully tried adding the member, but I sent in same code after I changed it.  I was only using $_.name after the group-object cmdlet, since the Name property is then the version of vSphere.  I was trying some different things when I sent that last piece of code. 

0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

Wow, that looks nice.  Thanks for your help, here is part of the script:

$vVersions = $AllESXiHost | Group Version | Select Count, Name
$ESXiModel = $AllESXiHost | group Model | Select Name, Count
$ESXiInfo = New-Object -TypeName PSObject
$ESXiInfo | Add-Member -MemberType NoteProperty -Name ESXihostCount -Value ($AllESXiHost).count
$vVersions | Foreach { Add-Member -InputObject $ESXiInfo -MemberType NoteProperty -Name "vSphere Version $($_.Name)" -Value $_.Count }
$ESXiInfo | Add-Member -MemberType NoteProperty -Name "Hardware Model" -Value $ESXiModel
Write $ESXiInfo | fl

It outputs:

ESXihostCount         : 25

vSphere Version 5.0.0 : 22

vSphere Version 4.1.0 : 7

I'm going to change some things around, but now I see what I need to do.  Thanks Smiley Happy

0 Kudos