What it does...

This function I wrote will return an object which contains the unique name of each OS for guests on a vCenter server. It will also show you the total number of VMs with that OS.

What it needs to run...

This function takes the parameter $vCenter. This should be the name of a vCenter server in your environment. You can also call the function as part of a foreach loop if you have multiple vCenter servers, running it once for each server and then returning that into another variable.

The Code:

function Get-VMOSList {
    [cmdletbinding()]
    param($vCenter)
    
    Connect-VIServer $vCenter  | Out-Null
    
    [array]$osNameObject       = $null
    $vmHosts                   = Get-VMHost
    $i = 0
    
    foreach ($h in $vmHosts) {
        
        Write-Progress -Activity "Going through each host in $vCenter..." -Status "Current Host: $h" -PercentComplete ($i/$vmHosts.Count*100)
        $osName = ($h | Get-VM | Get-View).Summary.Config.GuestFullName
        [array]$guestOSList += $osName
        Write-Verbose "Found OS: $osName"
        
        $i++    
 
    
    }
    
    $names = $guestOSList | Select-Object -Unique
    
    $i = 0
    
    foreach ($n in $names) { 
    
        Write-Progress -Activity "Going through VM OS Types in $vCenter..." -Status "Current Name: $n" -PercentComplete ($i/$names.Count*100)
        $vmTotal = ($guestOSList | ?{$_ -eq $n}).Count
        
        $osNameProperty  = @{'Name'=$n} 
        $osNameProperty += @{'Total VMs'=$vmTotal}
        $osNameProperty += @{'vCenter'=$vcenter}
        
        $osnO             = New-Object PSObject -Property $osNameProperty
        $osNameObject     += $osnO
        
        $i++
    
    }    
    Disconnect-VIserver -force -confirm:$false
        
    Return $osNameObject
}

Here is some example output (I tested it within another script I wrote). 
I blacked out the vCenter server name for security reasons.

 

Here is an example of the code I use to wrap it:

In this example the variables that already exist are:

$vCenterServers (this is an array of my vCenter servers)
$vCenter              (this is a parameter of my main script, the value of "all" is what the example below shows)
$getGuestOSList (this is a boolean parameter my script uses. What you see below is what happens if it is $true)

The below code will go through each of the individual vCenter servers and use the function above to build the variable $guestOSObjects with the output.

if (Get-View $DefaultViserver.ExtensionData.Client.ServiceContent.SessionManager) {Disconnect-VIServer * -confirm:$false -force;Write-Host "Disconnecting VI Server Sessions" -foregroundColor $foregroundColor}

if ($getGuestOSList) {
    
    Switch ($vCenter) {
    {$_ -like "all"} {
        
        $i = 0
        
        Foreach ($v in $vCenterServers) {
           
            $vCenter = $vcenterServers[$i]
            Write-Progress -Activity "Looking up VM Guests" -Status "Current vCenter Server: $vCenter" -PercentComplete ($i/$vCenterServers.Count*100)
            [array]$GuestOSObjects += Get-VMOSList $vCenter
      
            $i++
        
        }
        
    Return $guestOSOBjects
    
    }
    
}