Find vSphere VM locations: Folder, vApp and Resource Pool

The vSphere client doesn’t seem to give you a nice overview where you can see all the location data about your virtual machines. You can see the Folder and vApp by expanding all the branches in the VMs & Templates view, you can see the vApp and Resource Pool in the Hosts and Clusters view.

This script displays all of it in one view, and thanks to the Out-DataGrid cmdlet is sortable and searchable. I’ve also added the ability to save the output as XML for later examination, as the script takes a while to run. You need to have the PowerCLI modules loaded and already done a Connect-VIServer before running the script.

$Result = @()
$DatacenterName = "RCMTechMain"
$VMsProcessed = 0

Function Get-SaveFileName($initialDirectory){   
    [System.Reflection.Assembly]::LoadWithPartialName("") | Out-Null
    $SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
    $SaveFileDialog.initialDirectory = $initialDirectory
    $SaveFileDialog.filter = "XML files (*.XML)| *.XML"
    $SaveFileDialog.ShowDialog() | Out-Null

Write-Progress -Activity "Get all VMs" -PercentComplete (0)
$VMs = Get-VM -Location (Get-Datacenter -Name $DatacenterName)

foreach($VM in $VMs){
    $obj = New-Object system.object
    $FolderTemp = ""
    $Folder = ""
    $FolderText = "Folder"
    while($FolderTemp -ne $DatacenterName){
        $FolderTemp = (Invoke-Expression -Command ("`$VM."+$FolderText)).Name
        if($FolderTemp -ne "vm"){
            $Folder = "\" + $FolderTemp + $Folder
        if($FolderTemp -eq $null){
            $FolderTemp = $DatacenterName
            $Folder = "\" + $DatacenterName
        $FolderText = $FolderText + ".Parent"

    $obj | Add-Member -MemberType NoteProperty -Name VMName -Value $VM.Name
    $obj | Add-Member -MemberType NoteProperty -Name PowerState -Value $VM.PowerState
    $obj | Add-Member -MemberType NoteProperty -Name Folder -Value $Folder
    $obj | Add-Member -MemberType NoteProperty -Name vApp -Value $VM.VApp.Name
    if($VM.ResourcePool.Name -eq "Resources"){
        $obj | Add-Member -MemberType NoteProperty -Name ResourcePool -Value $null
    } else {
        $obj | Add-Member -MemberType NoteProperty -Name ResourcePool -Value $VM.ResourcePool.Name
    $Result += $obj

    Write-Progress -Activity "Getting VM details" -PercentComplete ($VMsProcessed/$VMs.Count*100)

$OutPath = Get-SaveFileName -initialDirectory ([environment]::GetFolderPath("mydocuments"))
if($OutPath -ne ""){
    $Result | Export-Clixml -Path $OutPath
$Result | Out-GridView -Wait

Set the $DatacenterName to your datacentre name as seen in the vSphere client (or you could do a Read-Host instead).

The folder path is a bit fiddly to work with, hence the while loop. The immediate folder that the VM is located in can be found via $VM.Folder. This will be blank if it’s not in a folder, so for consistency with the vSphere client I’m setting their folder path to the same root as those VMs in folders. If it is in a folder, we then loop looking at the $VM.Folder.Parent, $VM.Folder.Parent.Parent, and so on until we reach the folder that is the name of the datacentre. All the VMs not in a folder seem to be in a root folder called “vm” which doesn’t show in the vSphere client, so I’m ignoring this and not showing it in the resultant folder path.

I’m not displaying nested resource pools as I don’t have any. They work roughly along the lines of the folders though, so you get $VM.ResourcePool, then $VM.ResourcePool.Parent etc. Implementing this functionality has been left as an exercise for the reader ;-)

Then, as with previous scripts, I’m writing the output to an object, which gets added to an array. I’ve added a progress bar as the data retrieval can take a while, and progress bars are easy.

Then we repeat for the next VM.

Finally, you’re prompted if you want to save the file (cancel this if you don’t want to save it). If you do save, the array of objects is dumped to file via Export-Clixml. Then we display the array via Out-GridView.

To open a previously saved XML file you just use Import-Clixml and pipe it to Out-GridView. The machine you do this on doesn’t need to have the PowerCLI stuff, it only needs PowerShell as we’re just reading data in from a file.

To make this even easier, I’ve got a small script that’ll mean you don’t even have to go near a PowerShell prompt.

This entry was posted in PowerShell, Scripting, vSphere and tagged , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.