VMware View PowerCLI Script to Discover Un-used Virtual Machines

Version 1

    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("

    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)
                        $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 = "
    You selected No.  User Assignment NOT removed"
                    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 = "
       $colUnassigned | Export-Csv c:\temp\UnassignedVMs$($currentDate).csv          #export VMs unassigned and date file