Automating Desktop in ‘Already Used’ State in VMware View –Part 2

Sometimes non-persistent desktop pools become unusable over time. If a desktop that is set to refresh on log off is reset, the desktop goes into the Already Used state. This security feature prevents any previous session data from being available during the next log in.

Note: The View Desktop can also go into a Already Used state if a virtual machine is powered on in another ESX host in the cluster in response to a HA event or if it failed before a power on. VMware KB1000590

An easy way to identify a desktop that is in Already Used state is to look at View Manager status under the inventory tab – Status. The VMware View Desktop VM state displayed in the dashboard is a mix of ADAM data and a volatile state based on the latest agent stats reported to the View broker. Simple looking into the ADAM will not help in deducing what is the real Desktop VM state. At this time there’s no equivalent to looking at the state string in the Admin UI in the supported PowerShell cmdlets.

In this particular case you should be able to determine the desktop state by checking both of the following are true:

  1. VM is in READY state, online and has zero sessions [use Get-DesktopVm cmdlet]
  2. Machine entry in ADAM has the pae-dirtyfornewsessions attribute set to 1 [Look up object in ADAM using the id in check 1].

Manually checking based on data from ADAM is not supported by VMware as it’s considered internal and may change.I have previously discussed this same subject and proposed a similar solution. Automating Desktop in ‘Already Used’ State in VMware View.

VMware’s Consulting Architect, Andrea Siviero, has written another PowerShell script that detect and revert snapshot of desktops in “Already Used” state. With his consentient I am publishing the script here. Well-done Andrea!

[css lang=”plain” autolinks=”false” classname=”myclass” collapse=”false” firstline=”1″ padlinenumbers=”false” gutter=”true” smarttabs=”true” tabsize=”10″ toolbar=”true”]
Checks against ADAM for Desktop in "Already Used" status and send a Refresh
<A detailed description of the script>
.PARAMETER <paramName>
$viewServer – The View Connection Server you want to check against
<An example of using the script>
Andrea Siviero (c) 2011 Sivix

$view_snapin_name = "VMware.View.Broker"

# Defines variables used in the script
$ViewServer = "localhost"

$ViewSnapinLoaded = Get-PSSnapin | Where-Object { $_.Name -eq $view_snapin_name }
add-PSSnapin $view_snapin_name

# Defines log and txt files used in the script. It not exists; creates them.
$tmpLogFile = $MyInvocation.MyCommand.path
$LogFile = $tmpLogFile.Substring(0,$tmpLogFile.Length – 4) + ".log"

# Defines function for writing to logfile
Function Write-Log($Msg){
$date = Get-Date -format dd/MM/yyyy
$time = Get-Date -format HH:mm:ss
Add-Content -Path $LogFile -Value ($date + " " + $time + " " + $Msg)

# Specify the LDAP path to bind to
$LDAPPath = ‘LDAP://’ + $viewServer + ‘:389/OU=Servers,DC=vdi,DC=vmware,DC=int’
$LDAPEntry = New-Object DirectoryServices.DirectoryEntry $LDAPPath

# Create a selector and start searching from the path specified in $LDAPPath
$Selector = New-Object DirectoryServices.DirectorySearcher
$Selector.SearchRoot = $LDAPEntry
# filter dirtyfornewsessions in state READY with no Composer tasks
$Selector.Filter = "(&(objectClass=pae-VM)(pae-dirtyfornewsessions=1)(pae-vmstate=READY)(pae-svivmoperationprogress=0)(pae-svivmoperationstatus=completed))"

# Run the FindAll() method and limit to only return what corresponds to Desktops in VMware View with Applied Filter
$VMDesktops = $Selector.FindAll()
$RemoteSessions = Get-RemoteSession
Write-Log -Msg "Searching in $($VMDesktops.Count) Desktops"
$errMessage = ""
$ErrorRefresh = ""
$NumAlreadyUsed = 0

# Loop thru each desktop to find dirty not DISCONNECTED/CONNECTED and Agent OK = Already Used
foreach ($VMDesktop in $VMDesktops) {
$attribute = $VMDesktop.Properties
$DNSname = $attribute.iphostnumber
$Found = 0
foreach ($RemoteSession in $RemoteSessions) {
if ($RemoteSession.DNSName -match $DNSname) { $Found = 1 }
if (-not ($Found)) {
$DesktopName = $attribute.’pae-displayname’
$Poolid = $(Get-DesktopVM -Name $DesktopName).pool_id
$AgentCheck = vdmadmin.exe -A -d $($Poolid) -m $($DesktopName) -getstatus
if ($AgentCheck -match "agentErrorText = OK") {
$NumAlreadyUsed = $AlreadyUsed +1
$now = Get-Date
Send-LinkedCloneRefresh -machine_id $ -schedule $now -forceLogoff $true -ErrorVariable ErrorRefresh -ErrorAction:SilentlyContinue
$errMessage = "Already Used found: Name=$($DesktopName), DNS=$($DNSname),CN=$($,Pool=$Poolid, Refresh Needed $ErrorRefresh"
Write-Log -Msg $errMessage
if ($errMessage -eq "") { Write-Log -Msg "Already Used not found"}
else { Write-Log -Msg "Found $($NumAlreadyUsed) Already Used"}

This article was first published by Andre Leibovici (@andreleibovici) at

Leave a Reply