VMware View PowerCLI Script to Discover Un-used Virtual Machines

VMware View PowerCLI Script to Discover Un-used Virtual Machines

VM sprawl is a concern for View Administrators and routine maintenance to discover unused virtual desktops is a good practice.  Below is a View PowerCLI script I’ve created to expose virtual machines that have not been used in a given period of time, set under $timeSpan variable.

The script will query View and populate an array of virtual machines, assigned userIDs, and LastWriteTime of user profile while excluding others such as replicas, master VMs, or unassigned.

Script will then prompt to unassign user from vm, default response is NO. In this script I’m interested in any vm not used for more than 180 days.  Upon completion two comma separated files are exported to C:\Temp, an AgingVMs-MM-DD-YYYY.csv and UnAssignedVMs-MM-DD-YYYY.csv.

System Administrators will need to modify the following areas of this script to align with their environments

·        $timeSpan = New-TimeSpan -Days 180

·        $persistentDrive = "\D$\Users\"

·        vmName*

·        Export-Csv c:\temp\

#*****************************************

#

# Author: Silas Sunday

# Version: 1.0

# Date: October 30, 2017

#

# Purpose: Used to discover unused VDI clones based

#          on user profile folder LastWriteTime property value.

#

#*****************************************

$currentDate = Get-Date -UFormat "-%m-%d-%Y"           #get current date and format to Month-Day-Year to append at end of CSV exported File

$replyYes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Remove User Ownership."

$replyNo = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Do NOT Remove User Ownership."

$timeSpan = New-TimeSpan -Days 180 #establish date in time, where items older that xDays are subject to unassignment

$colUnassigned = @()    #create empty array to hold list of users unassigned from vdi clones

$colFolders = @()             #create empty array to hold path results

$colResults = @()             #create empty array to update results of discovery

$vmList = @()                    #create empty array to hold vdi clone information

$persistentDrive = "\D$\Users\"             #path variable to persistent drive where user profiles are housed

#query connection manager, pass vm Name and assigned User to $vmList Array.  Excluding vms begining with vmName*.
#for example:  exclude all vm names begining with "
master*" and "replica*"
$vmList = Get-DesktopVM | Select Name, user_displayname | Where {$_.Name -notlike "
vmName*" -and $_.Name -notlike "vmName*"  #add more exclusion is needed

foreach ($i in $vmList)
{
                #remove "
DomaindName.DomainName\" string information from user_displayname array element
                #and replace with nothing ""  for example: f2.com\UserID converted to -> UserID
                $i.user_displayname = $i.user_displayname.Replace("
DomainName.DomainName\","")
}

foreach ($i in $vmList)
{
                if ($i.user_displayname -eq $null){continue}       #skips vm that is not assigned
                $testPath = Test-Path "
\\$($i.Name)$($persistentDrive)$($i.user_displayname)"             #checks if folder exists, return TRUE or FALSE
                if ($testPath -eq $false) {continue}          #vm does not contain DriveLetter$\User\UserID folder.  Continue to next VM
                $userPath = "
\\$($i.Name)$($persistentDrive)$($i.user_displayname)" #build full path to user folder
                $colFolders = Get-ItemProperty $userPath | Select Root, Name, LastWriteTime                #Gets properties for Root, Name, and LastWriteTime
                $LWT = (Get-ItemProperty $userPath).LastWriteTime
                $colResults += $colFolders           #update array with Root, Name, LastWriteTime
#*****************************************
#This block will perform vdi user unassignment
if (((Get-Date) - $LWT) -gt $timeSpan)   #if current date minus LaswWriteTime is greater than $timeSpan days then
    {
                $titleMSG = "
Remove User Ownership"
                $questionMSG = "
User $($i.user_displayname) last write time for $($i.Name) is $($LWT) Do you want to remove user ownership from clone? (Default NO)"
                $usrOptions = [System.Management.Automation.Host.ChoiceDescription[]]($replyYes, $replyNo)
                $usrResult = $host.UI.PromptForChoice($titleMSG, $questionMSG, $usrOptions, 1)        #0 sets default to YES, 1 sets default to NO
                Switch ($usrResult)
                {
                  0
                   {
                    $colUnassigned += $colFolders              #update array with systems unassigned for export to CSV
                    "
You selected Yes.  User Assignment will be removed";
                    Remove-UserOwnership -machine_id (Get-DesktopVM -Name $i.Name).machine_id               #command to unassign selected user from vm
   $vmRemoved = "
TRUE"
                   }
                  1
                   {
                    "
You selected No.  User Assignment NOT removed"
                   }
                }                           
   }
Else
   {
                Continue             #vm has been access recently. Continue to next vm
   }
}
#*****************************************
$colAging = $colAging | Sort-Object LastWrietTime
$colUnassigned = $colUnassigned | Sort-Object LastWriteTime

$colUnassigned | Export-Csv c:\temp\AgingVMs$($currentDate).csv          #export VMs aging and date file

if ($vmRemoved = "
TRUE")
{
   $colUnassigned | Export-Csv c:\temp\UnassignedVMs$($currentDate).csv          #export VMs unassigned and date file
}

Attachments
Comments

Thanks for the script!  I am having a few issues though.  Were you able to get it to work as-is?

In the below line.  Should this be Get-DesktopVM or just Get-VM?  I also added a closing } to the end.  I get that to work but the entire script errors out on the ($i.user_displayname -eq  parameter. 

$vmList = Get-DesktopVM | Select Name, user_displayname | Where {$_.Name -notlike "vmName*" -and $_.Name -notlike "vmName*"  #add more exclusion is needed

@gpenunuri if you haven't already figured it out, you need to do this on one of your connection servers.

1) Login to one of your connection servers

2) Open PowerShell in Privileged mode

3) Run "Add-PSSnapin vmware.view.Broker"

once you do that, "Get-DesktopVM" should be able to list all your VMs.

Best of luck! 

Version history
Revision #:
1 of 1
Last update:
‎11-01-2017 07:13 AM
Updated by: