Azure Windows Virtual Desktop: Avoid the fresh hell of stale user sessions

Microsoft recently announced a new version of Azure Windows Virtual Desktop. WVD 2.0 uses the Azure Resource Manager model. WVD 1.0 used the Azure classic model, which required a new WVD tenant to be created in the cloud. WVD 2.0 follows the ARM model, which supports assigning WVD components such as host pool, session hosts, etc. to Azure resource groups.

Important: This is an essential read for organizations evaluating Azure Windows Virtual Desktop to support remote workforce scenarios and would like to reduce daily helpdesk calls related to WVD.

While organizations are evaluating Azure Windows Virtual Desktop for a remote workforce, the lack of information about WVD at Microsoft and other sites keeps IT administrators and architects busy in making sure all components of WVD are evaluated to ensure WVD meets both functional and non-functional requirements. I have been working on large WVD environments recently. As part of our recent WVD project for a customer, we deployed WVD for more than 3,000 users, and more than 450 session hosts were deployed to accommodate 3,000 users. During the sustain-and-maintain phase, we faced issues with WVD user sessions, which, in turn, resulted in daily calls to the helpdesk. This article provides information on where user session details are stored and how to determine if a user is actually active or disconnected.

Azure-Windows-Virtual-Desktop
Shutterstock

WVD user sessions in Azure Windows Virtual Desktop database

It is essential to understand that WVD keeps a volatile database in Microsoft datacenter for each customer. The internal WVD database is responsible for keeping user-session information. The user-session information such as user principal name, AD user name of the user, session creation time, session ID, host pool name to which the user is connected to, session hostname to which the user is connected to, session state, and other information are stored in the WVD database. When a user connects to a host pool in a WVD environment, the following chain of events take place:

  • The RDP-SXS agent, which is running on the session host, sends user sessions data to the WVD database.
  • WVD database receives the data and updates the user session details.
  • WVD database also keeps session state for each user, such as whether the user session is in an “active” or “disconnected” state.

Why a central WVD database?

There are two important reasons why there is a need to keep a central WVD database:

  • If there is no central WVD database, then a WVD administrator would have to query all session hosts to see the status of each user session.
  • Connecting to each session host to collect user-session information is a time-consuming process and might increase the time to troubleshoot an issue.
  • All WVD PowerShell cmdlets require to connect to a central database to collect user and session hosts related information.

WVD user session states in the Azure Windows Virtual Desktop database

The WVD database can hold two types of session states: Users in disconnected states and users in active states. The “users in disconnected states” are users who are connected to a host pool in a WVD environment, but their connections still remain connected to the session hosts. The “users in active states” are connections that are actually active on the session hosts. The WVD database keeps the data for a period of time and is refreshed during the WVD database refresh process. The entries in the WVD database are removed, and there is no update about an entry from the RDP-SXS agent.

There is an important aspect that we need to understand. A user who is connected to a session host might not have an updated entry in the WVD database. For example, when you query the WVD database using the Get-AzWVDUserSessions PowerShell cmdlet from a particular session host, the command will connect to the WVD database to get the session state of the user. If the user is already “disconnected” from the session host and if the user’s status in the WVD database says “Active,” that means you are collecting incorrect information for that user from the WVD database. In other words, the user is actually not active. Remember, it takes a few minutes or more before the RDP-SXS agent can update the user session details in the WVD database.

WVD user sessions: Normal vs. stale sessions

As you can see from the previous section of this article, the WVD database can contain both normal and stale sessions, but let’s understand the difference between them. A “stale” session is a session that shows “active” in the WVD database, but the session host virtual machine to which the user is connected to is actually “turned off.” On the other hand, a “normal session” is a session that shows “Active” and the session host virtual machine to which the user is connected to is “turned on.” For example, if a user shows “active” in the WVD database and if the session host virtual machine is “off,” then that user is actually not active and would come under the “stale” sessions category. However, when you execute the Get-AzWVDUserSession PowerShell cmdlet to get the user session details from a host pool, the Get-AzWVDUserSession cmdlet actually doesn’t get the session host virtual machine status, and that’s why you can’t figure out if the session is actually a “normal” or “stale” session.

Getting the actual state of a user session

To get the actual session state of an Azure Windows Virtual Desktop user, you can execute the Get-AzWVDUserSession PowerShell cmdlet, but you also need to get the session host virtual machine status. The following PowerShell script, which was retrieved from Wintellisys WVD Manager, can be used to get the user sessions from a specified host pool and also get the virtual machine status of the session host to which the user is connected to.

Important: Please modify “$HostPool” and “$ResourceGroupName” variables before executing the below script.

$SessionsResultFile = "C:\Temp\Sessions.CSV"
Remove-item $SessionsResultFile -ErrorAction SilentlyContinue
$STR = "AD User Name, Session State, session host Name, VM Status"
Add-Content $SessionsResultFile $STR
$HostPool = "ThisHostPool"
$ResourceGroupName = "ThisResourceGroup"
$AllUsers = Get-AzWvdUserSession -ResourceGroupName $FinalResGroup -HostPoolName $PoolName | Select-Object *
ForEach ($Item in $AllUsers)
{
$ThisHost = $Item.SessionHostName
$ThisState = $Item.SessionState
$ThisUName = $Item.ADUserName
$VMName, $B = $ThisHost.Split(".")
$Status = Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VMName -Status | Select-Object *
$VMStatus = $Status.Statuses[1].DisplayStatus
$STR = $ThisUName+","+$ThisState+","+$ThisHost+","+$VMStatusNow
Add-Content $SessionsResultFile $STR
}

Once the script has finished executing, you will see a result file C:\Temp\Sessions.CSV, which contains the AD user name, session hostname, session state, and VM status of the session host as it shows in the screenshot below of the report file:

Azure Windows Virtual Desktop

As you can see in the screenshot, the script collected user session status for six users and found that Corp\User3 and Corp\User4 are shown as “active” from the WVD database, but the session host virtual machine status says “VM deallocated.” It clearly indicates that the Corp\User3 and Corp\User4 are stale connections.

While the above script can be helpful in retrieving the user sessions states along with the session host virtual machine status, to collect session states and session host VM status for all host pools, you will be required to use a “for each” loop that checks for all host pools, or use Wintellisys WVD Manager. Wintellisys WVD Manager provides a user sessions manager component that can help you perform all management tasks such as removing stale sessions, logging off multiple users, and so on, as shown in the screenshot below:

Azure Windows Virtual Desktop

As you can see in the screenshot, it shows the session state of each user, the session host to which the user is connected to and the actual virtual machine status of the session host. The last column, “Account Type,” shows whether the session is a “normal” session or a “stale” session. You can select all stale sessions in the pane and then click on “logoff selected” to remove all stale sessions.

What if stale sessions are not removed?

If you do not remove stale sessions, these users cannot create another session to the same host pool in the WVD environment. So, it is important that all stale sessions are removed from the WVD environment. Removing stale sessions can also help in reducing the helpdesk calls if a user is not able to connect to a host pool in a WVD environment. Wintellisys WVD Manager provides a way to remove all stale sessions periodically by configuring a WVD notification as shown in the screenshot below:

The notification is processed every 45 minutes and can be configured for all managed WVD tenants.

You can also design a PowerShell script that uses Remove-AzWvdUserSession to remove user sessions from host pools and then schedule the script to run every 45 minutes.

Featured image: Shutterstock

About The Author

4 thoughts on “Azure Windows Virtual Desktop: Avoid the fresh hell of stale user sessions”

  1. The PS above does not run – “Get-AzWvdUserSession : Cannot bind argument to parameter ‘ResourceGroupName’ because it is an empty string.”

    1. This PS Code should run (Without VMStatus):

      #Please modify “$SessionsResultFile”, “$HostPool”, and “$ResourceGroupName” variables before executing the below script.
      #Code without PowerState (VMStatus) for faster run.
      Connect-AzAccount

      $date=Get-Date -Format “MM-dd-yyyy HH-mm”
      $SessionsResultFile = “C:\PSCode\WVD\Output\WVDSessionsInfo\WVDSessionsInfo $date.CSV”
      #Remove-item $SessionsResultFile -ErrorAction SilentlyContinue

      $STR = “AD User Name, Session State, Session host Name”
      #$STR = “AD User Name, Session State, Session host Name, VM Status”
      Add-Content $SessionsResultFile $STR

      $HostPool = “zeu1-bis-prd-wvd2-pool03”
      $ResourceGroupName = “zna1-bis-prd-wvd2-rg”

      $AllUsers = Get-AzWvdUserSession -ResourceGroupName $ResourceGroupName -HostPoolName $HostPool | Select-Object *

      ForEach ($Item in $AllUsers)
      {
      $ThisHost = $Item.Name
      $ThisState = $Item.SessionState
      $ThisUName = $Item.ActiveDirectoryUserName
      $VMName, $B = $ThisHost.Split(‘/.’)[1]
      #$VMStatusNow = Get-AzVM -Name $VMName -Status | Select -expand PowerState
      #$STR = $ThisUName+”,”+$ThisState+”,”+$ThisHost+”,”+$VMStatusNow
      $STR = $ThisUName+”,”+$ThisState+”,”+$ThisHost

      Add-Content $SessionsResultFile $STR
      }

      Disconnect-AzAccount

  2. This PS Code should run:

    #Please modify “$SessionsResultFile”, “$HostPool”, and “$ResourceGroupName” variables before executing the below script.
    #May take a while to run depending on amount of sessions hosts as it seperately queries for PowerState
    Connect-AzAccount

    $date=Get-Date -Format “MM-dd-yyyy HH-mm”
    $SessionsResultFile = “C:\Temp\WVDSessionsInfo $date.CSV”
    #Remove-item $SessionsResultFile -ErrorAction SilentlyContinue

    $STR = “AD User Name, Session State, Session host Name, VM Status”
    Add-Content $SessionsResultFile $STR

    $HostPool = “HostPoolName”
    $ResourceGroupName = “RG-Name”

    $AllUsers = Get-AzWvdUserSession -ResourceGroupName $ResourceGroupName -HostPoolName $HostPool | Select-Object *

    ForEach ($Item in $AllUsers)
    {
    $ThisHost = $Item.Name
    $ThisState = $Item.SessionState
    $ThisUName = $Item.ActiveDirectoryUserName
    $VMName, $B = $ThisHost.Split(‘/.’)[1]
    $VMStatusNow = Get-AzVM -Name $VMName -Status | Select -expand PowerState
    $STR = $ThisUName+”,”+$ThisState+”,”+$ThisHost+”,”+$VMStatusNow

    Add-Content $SessionsResultFile $STR
    }

Leave a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top