title: VMWare VMDK mapping to Windows Drive Letters
body: <p>this code almost works, it maps VWare VMDK to windows drives. The code is not mine.</p>
  
  <p>Among other info it will return "<strong>DD-SERV-01_15.vmdk</strong> for VM <strong>MAIN</strong> is Drive letter <strong>G:</strong>"</p>
  
  <p>The script will prompt for credentials and proceeds to map however something goes wrong and only the last VM / Drive is is saved as output - I was hoping someone could take a look and update / fix the code so that it saves all output please?</p>
  
  <p>Thanks.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>#Get VMware Disk Usage
  # Created by Hugo Peeters
  # http://www.peetersonline.nl
  # VARIABLES
  $Decimals = 1
  $VCServer = "SERVERNAME"
  # SCRIPT
  # Connect to VC
  Write-Progress "Gathering Information" "Connecting to Virtual Center" -Id 0
  $VC = Connect-VIServer $VCServer
  # Create Output Collection
  $myCol = @()
  # List Datastores (Datastore Name)
  Write-Progress "Gathering Information" "Listing Datastores" -Id 0
  $Datastores = Get-Datastore | Sort Name
  # List vms
  Write-Progress "Gathering Information" "Listing VMs and Disk Files" -Id 0
  $VMSummaries = @()
  ForEach ($vm in (Get-VM))
   {
   $VMView = $VM | Get-View
   ForEach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | Where {$_.DeviceInfo.Label -match "SCSI Controller"}))
    {
    ForEach ($VirtualDiskDevice  in ($VMView.Config.Hardware.Device | Where {$_.ControllerKey -eq $VirtualSCSIController.Key}))
     {
     $VMSummary = "" | Select VM, HostName, PowerState, DiskFile, DiskName, DiskSize, SCSIController, SCSITarget
     $VMSummary.VM = $VM.Name
     $VMSummary.HostName = $VMView.Guest.HostName
     $VMSummary.PowerState = $VM.PowerState
     $VMSummary.DiskFile = $VirtualDiskDevice.Backing.FileName
     $VMSummary.DiskName = $VirtualDiskDevice.DeviceInfo.Label
     $VMSummary.DiskSize = $VirtualDiskDevice.CapacityInKB * 1KB
     $VMSummary.SCSIController = $VirtualSCSIController.BusNumber
     $VMSummary.SCSITarget = $VirtualDiskDevice.UnitNumber
     $VMSummaries += $VMSummary
     }
    }
   Clear-Variable VMView -ErrorAction SilentlyContinue
   }
  # Loop through Datastores
  ForEach ($Datastore in $Datastores)
   {
   # List vmdk files in datastore (vmdk Name)
   Write-Progress "Gathering Information" ("Processing Datastore {0}" -f $Datastore.Name) -Id 0
   $DSView = $Datastore | Get-View
   $fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
   $fileQueryFlags.FileSize = $true
   $fileQueryFlags.FileType = $true
   $fileQueryFlags.Modification = $true
   $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
   $searchSpec.details = $fileQueryFlags
   $searchSpec.sortFoldersFirst = $true
   $dsBrowser = Get-View $DSView.browser
   $rootPath = "["+$DSView.summary.Name+"]"
   $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)
   ForEach ($result in $searchResult)
    {
    ForEach ($vmdk in ($result.File | ?{$_.Path -like "*.vmdk"} | Sort Path))
     {
     Write-Progress "Gathering Information" ("Processing VMDK {0}" -f $vmdk.Path) -Id 1
     Write-Host "=============================================================================="
     # Find vm using the vmdk (VM Name)
     $VMRef = ($VMSummaries | ?{$_.DiskFile -match $Datastore.Name -and $_.DiskFile -match $vmdk.Path})
     "VMDK {0} belongs to VM {1}" -f $vmdk.Path, $VMRef.VM
     If ($VMRef.Powerstate -eq "PoweredOn")
      {
      Write-Host "VM is powered on" -ForegroundColor "yellow"
      $Partitions = Get-WmiObject -Class Win32_DiskPartition -ComputerName $VMRef.HostName
      If ($?)
       {
       $Disks = Get-WmiObject -Class Win32_DiskDrive -ComputerName $VMRef.HostName
       $LogicalDisks = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $VMRef.HostName
       $DiskToPartition = Get-WmiObject -Class Win32_DiskDriveToDiskPartition -ComputerName $VMRef.HostName
       $LogicalDiskToPartition = Get-WmiObject -Class Win32_LogicalDiskToPartition -ComputerName $VMRef.HostName
       Write-Host "Read partition and disk information" -ForegroundColor "yellow"
       # Match disk based on SCSI ID's
       $DiskMatch = $Disks | ?{($_.SCSIPort - 1) -eq $VMRef.SCSIController -and $_.SCSITargetID -eq $VMRef.SCSITarget}
       If ($DiskMatch -eq $null){Write-Warning "NO MATCHES!"}
       Else
        {
        Write-Host "Found match:" -ForegroundColor "yellow"
        $DiskMatch
        # Find the Partition(s) on this disk
        $PartitionsOnDisk = ($DiskToPartition | ?{$_.Antecedent -eq $DiskMatch.__PATH})
        If ($PartitionsOnDisk -eq $null){Write-Warning "NO PARTITIONS!"}
        Else
         {
         ForEach ($PartitionOnDisk in $PartitionsOnDisk)
          {
          Write-Host "Disk contains partition" -ForegroundColor "yellow"
          $PartitionOnDisk.Dependent
          $PartitionMatches = $Partitions | ?{$_.__PATH -eq $PartitionOnDisk.Dependent}
          ForEach ($PartitionMatch in $PartitionMatches)
           {
           $LogicalDiskRefs = $LogicalDiskToPartition | ?{$_.Antecedent -eq $PartitionMatch.__PATH}
           If ($LogicalDiskRefs -eq $null)
            {
            Write-Warning "NO LOGICAL DISKS!"
            }
           Else
            {
            ForEach ($LogicalDiskRef in $LogicalDiskRefs)
             {
             $LogicalDiskMatches = $LogicalDisks | ?{$_.__PATH -eq $LogicalDiskRef.Dependent}
             ForEach ($LogicalDiskMatch in $LogicalDiskMatches)
              {
              Write-Host "Matching Logical Disk:" -ForegroundColor "yellow"
              $LogicalDiskMatch
              # Create Output Object
              $myObj = "" | Select Datastore, DSSizeGB, DSFreeGB, DSPercentFree, DiskFile, VM, HardDisk, DriveLetter, DiskSizeGB, DiskFreeGB, PercFree
              # List datastore name
              $myObj.Datastore = $Datastore.Name
              # Determine datastore size in GB
              $myObj.DSSizeGB = [Math]::Round(($Datastore.CapacityMB * 1MB / 1GB),$Decimals)
              $myObj.DSFreeGB = [Math]::Round(($Datastore.FreeSpaceMB * 1MB / 1GB),$Decimals)
              # Determine datastore free space (DS%Free)
              $myObj.DSPercentFree = [Math]::Round((100*($Datastore.FreeSpaceMB/$Datastore.CapacityMB)),$Decimals)
              # List disk file name
              $myObj.DiskFile = $vmdk.Path
              # List VM Name
              $myObj.VM = $VMRef.VM
              # Determine virtual hard disk / logical drive
              $myObj.HardDisk = $VMRef.DiskName
              # Report driveletter
              $myObj.DriveLetter = $LogicalDiskMatch.DeviceID
              # Report Size
              $myObj.DiskSizeGB = [Math]::Round(($LogicalDiskMatch.Size / 1GB),$Decimals)
              # Report Free Space
              $myObj.DiskFreeGB = [Math]::Round(($LogicalDiskMatch.FreeSpace / 1GB),$Decimals)
              # Calculate Percentage free space
              $myObj.PercFree = [Math]::Round((100 * ([int]($LogicalDiskMatch.FreeSpace / 1MB) / [int]($LogicalDiskMatch.Size / 1MB))),$Decimals)
              Write-Host "RESULT:" -ForegroundColor "yellow"
              $myObj
              # Add output object to output collection
              $myCol += $myObj
              }
             Clear-Variable LogicalDiskMatches -ErrorAction SilentlyContinue
             }
            }
           Clear-Variable LogicalDiskRefs -ErrorAction SilentlyContinue
           }
          Clear-Variable PartitionMatches -ErrorAction SilentlyContinue
          }
         }
        Clear-Variable PartitionsOnDisk -ErrorAction SilentlyContinue
        }
       Clear-Variable DiskMatch -ErrorAction SilentlyContinue
       Clear-Variable Disks -ErrorAction SilentlyContinue
       Clear-Variable LogicalDisks -ErrorAction SilentlyContinue
       Clear-Variable DiskToPartition -ErrorAction SilentlyContinue
       Clear-Variable LogicalDiskToPartition -ErrorAction SilentlyContinue
       }
      Clear-Variable Partitions -ErrorAction SilentlyContinue
      }
     Else
      {
      Write-Host "VM is powered off" -ForegroundColor "yellow"
      }
     Clear-Variable VMRef -ErrorAction SilentlyContinue
     Write-Progress "Gathering Information" ("Processing VMDK {0}" -f $vmdk.Path) -Id 1 -Completed
     }
    }
   }
  # Disconnect from VC
  Disconnect-VIServer -Confirm:$False
  # OUTPUT
  Write-Host "==================================================="
  Write-Host "==================================================="
  $TotalDSFree = ($myCol | Select Datastore, DSFreeGB -Unique | Measure-Object DSFreeGB -Sum).Sum
  $TotalDSSize = ($myCol | Select Datastore, DSSizeGB -Unique | Measure-Object DSSizeGB -Sum).Sum
  $AverageDSFree =  [Math]::Round(100 * ($TotalDSFree / $TotalDSSize),$Decimals)
  $AverageDiskFree =  [Math]::Round(100 * (($myCol | Measure-Object DiskFreeGB -Sum).Sum / ($myCol | Measure-Object DiskSizeGB -Sum).Sum),$Decimals)
  Write-Host "Total DS Free: $TotalDSFree"
  Write-Host "Total DS Size: $TotalDSSize"
  Write-Host "Average DS Free Percentage: $AverageDSFree"
  Write-Host "Average Disk Free Percentage: $AverageDiskFree"
  $myCol | Export-Csv -NoTypeInformation 'C:\TEMP\VMwareDiskUsage.csv'</code></pre>
  </div>
  </div>
  </p>