VMware Cloud Community
pamiller21
Enthusiast
Enthusiast

Windows OS Version

I am trying to find a simple way to keep up with the MS Windows Audits.  They want to know what version everything is running, so I have a method to do this, but scripting will help me gather things better and a breeze in the future.  What I am looking to do is:

1) Is there a way to take a CSV or TSV file with VM names and put VM tags on them, so I can quickly tag x,y,&z with Windows 2012 Standard or something.

2) Can I make a report that would print the VMs by version and total it at the bottom.  Something like:

Windows 2012 Standard
x

y

z

Total: 3

Windows 2016 Standard....

This would make my life so much simpler! Thanks for any advice.

0 Kudos
11 Replies
LucD
Leadership
Leadership

This will all depend if you have VMware Tools installed and running on your VMs.

For the tagging you could do something like this

$csv = '.\vmnames.csv'

$categoryName = 'OS'


try{

    $cat = Get-TagCategory -Name $categoryName -ErrorAction Stop

}

catch{

    $cat = New-TagCategory -Name $categoryName -Cardinality Single -EntityType VM

}


Get-VM -Name (Import-Csv -Path $csv -UseCulture).VMName -PipelineVariable vm |

ForEach-Object -Process {

    if($vm.Guest.OSFullName){

        try{

            $tag = Get-Tag -Name $vm.Guest.OSFullName -Category $cat -ErrorAction Stop

        }

        catch{

            $tag = New-Tag -Name $vm.Guest.OSFullName -Category $cat

        }

        Get-TagAssignment -Entity $vm -Category $cat -ErrorAction SilentlyContinue |

        Remove-TagAssignment -Confirm:$false

        New-TagAssignment -Entity $vm -Tag $tag -Confirm:$false

    }

    else{

        Write-Host "Could not determine Guest OS for $($vm.Name)"

    }

}


For a report you can then do something like this

$categoryName = 'OS'

$cat = Get-TagCategory -Name $categoryName


Get-VM -Name (Import-Csv -Path .\vmnames.csv -UseCulture) -PipelineVariable vm |

Group-Object -Property {$_.Tag.Name} |

Select Name,@{N='Count';E={$_.Group.Count}}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
pamiller21
Enthusiast
Enthusiast

I gave this a go, but I got this error:

Get-VM : Cannot validate argument on parameter 'Name'. The argument is null or empty. Provide an argument that is not

null or empty, and then try the command again.

At C:\Users\milleran\Documents\VM-OS.ps1:17 char:14

+ Get-VM -Name (Import-Csv -Path $csv -UseCulture) -PipelineVariable vm ...

+              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Get-VM], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVM

The CSV is just a list of few VMs with commas, but that's all.

0 Kudos
LucD
Leadership
Leadership

The script assumes that the CSV looks like this

VMName

vm1

vm2

If your columnname is different (than VMName) you will have to update the propertyname on the Get-VM.
I just updated the code to reflect the VMName column from the example above.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
pamiller21
Enthusiast
Enthusiast

This is what I get now:

Get-VM      VM with name '@{VMName=Victoria-DC}' was not found using the specified

filter(s).

sorry for the format there.

0 Kudos
LucD
Leadership
Leadership

I suspect you don't have the VMName property on the Get-VM line


Get-VM -Name (Import-Csv -Path $csv -UseCulture).VMName -PipelineVariable vm |


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
pamiller21
Enthusiast
Enthusiast

That worked, but the problem I have is its pulling Windows Server 2016 or later, since VMware doesn't see the difference in 2016 & 2019.  I can provide a CSV list of the 2019 ones and then just need a script to apply those tags.

0 Kudos
LucD
Leadership
Leadership

If you just need to tag the 2019 ones, use that CSV.
You will have to change the Tag value.
Instead of using $vm.Guest.OSFullName you will need to have a static string with something like 'Windows 2019'.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
pamiller21
Enthusiast
Enthusiast

That worked great, now I am looking at the reporting piece and what I would like is it to just scan the whole inventory not just the csv at this point and return all OS tags with totals to an html page.  I tried to modify the lines but its still looking for variables within the CSV.

This has been a TREMENDOUS help so far though I really appreciate all this!

0 Kudos
LucD
Leadership
Leadership

Try like this

Get-TagAssignment -Category OS |

Group-Object -Property {$_.Tag.Name} |

Select Name,@{N='Count';E={$_.Group.Count}}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
pamiller21
Enthusiast
Enthusiast

Perfect, can it ignore powered off VMs and VMs in specified folders?

0 Kudos
LucD
Leadership
Leadership

Sure, something like this

$folderToSkip = 'MyFolder'

$vmToSkip = Get-Folder -Name $folderToSkip | Get-VM |

    Select -ExpandProperty Name


Get-TagAssignment -Category OS |

where{$_.Entity.PowerState -eq 'PoweredOn' -and $vmToSkip -notcontains $_.Entity.Name} |

Group-Object -Property {$_.Tag.Name} |

Select Name,@{N='Count';E={$_.Group.Count}}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos