Latest XenApp XenDesktop bandwidth utilization tests

Is it just me, or does it seem like every few releases Citrix finds ways to further reduce bandwidth consumption. When 7.13 came out, there were statements saying bandwidth utilization dropped. And in 7.17, we are hearing similar remarks. If we look at the latest releases, we see the following major improvements to the ICA protocol

  • 7.13:
    • Introduce glyph detection/caching algorithm – Beneficial for text-based workloads
    • Improve scroll detection
  • 7.17:
    • Update glyph detection/caching algorithm – Beneficial for text-based workloads
  • 7.18:
    • H.264 Build-to-Lossless – Beneficial for graphically interactive sessions
    • Progressive Display – Beneficial for low bandwidth and/or high latency connections

I want to see how these improvements impacts network utilization, so I ran my own simulations. I decided to run the same tests against the 7.11, 7.12, 7.13, 7.14, 7.15, 7.16, 7.17 and 7.18 releases.

Knowledge Worker – User Experience Policy

In the first graph, we have the following:

  • Workload: Knowledge Worker
  • Policy: Optimize for User Experience
  • Test Duration: 60 minutes
  • Sample Period: 1 second

I notice the following:

  • 7.13: A slight drop in cumulative bandwidth usage. This drop extends through the 7.17 release.
  • 7.18: A noticeable drop, most likely due to the H.264 Build-to-Lossless capability with the graphical knowledge worker workload.

Knowledge Worker – WAN Policy

Let’s change the policy and retest

  • Workload: Knowledge Worker
  • Policy: Optimize for WAN
  • Test Duration: 60 minutes
  • Sample Period: 1 second

Besides lower numbers, as we would expect with the optimize for WAN policy, we see similar bandwidth reductions in the 7.13 and 7.18 releases.

Knowledge Worker – Comparison

By looking at average bandwidth utilization across the 60 minute test, we can start to see these improvements a little easier. 

Task Worker – User Experience Policy

In the first graph, we have the following:

  • Workload: Task Worker
  • Policy: Optimize for User Experience
  • Test Duration: 60 minutes
  • Sample Period: 1 second


The 7.17 and 7.18 releases look crazy. This would be due to the improvements in glyph caching, which is extremely beneficial for text-based workloads, like Excel.  I compared the steep increases in the 7.11-7.16 graphs with the actual workload. Turns out these all align with Microsoft Excel. Imagine scrolling through a spreadsheet full of numbers. The glyph detection/caching improvements in 7.17 really shine on this portion of the simulation.

Task Worker – WAN Policy

If we change the policy to WAN and retest

  • Workload: Task Worker
  • Policy: Optimize for WAN
  • Test Duration: 60 minutes
  • Sample Period: 1 second

We see similar reductions in the 7.17 release.  In addition, we also see the introduction of the glyph caching in the 7.13 release with the optimize for WAN policy.

Task Worker – Comparison

When we change the graph to look at the estimated kilobits per second, the improvements are quite interesting for the Task Worker.

Based on all of these tests, workload changes and policy changes, there are essentially 3 distinct groupings of data based on improvements made to ICA:

  1. Group 1: 7.11 and 7.12
  2. Group 2: 7.13-7.16
  3. Group 3: 7.17-7.18

Stay tuned as I plan to keep running these standard tests on upcoming releases.

Daniel (Follow on Twitter @djfeller)
Citrix Workspace Poster
XenApp/XenDesktop On-Prem Poster
XenApp/XenDesktop Cloud Service Poster




XenServer PowerShell – New Windows VM from ISO

I tend to build many Windows VMs on XenServer and want a way to automate as much as possible.

I want to avoid using Sysprep.  I’m getting a Windows 10 ISO from Microsoft every 6 months (semi-annual release).  If I go with Sysprep, I have to manually create the VM, sysprep it, turn it into a template and finally create my VM.  Plus, how many times can I sysprep before I run into license issues and sysprep count?

Seems like a lot of waste and trouble.

Instead, I want to automatically build a VM from a newly downloaded ISO file. The challenge is I need to have an unattend.xml file within the ISO. Let’s see how to accomplish that.

Before I begin, I need the following items:

  • Unattend.xml for Windows 2016
  • Unattend.xml for Windows 10
  • (from Windows ISO .\boot\
  • OSCDIMG.exe (from Windows Assessment and Deployment Kit C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg)
  • XenServer template for Windows 2016 (Blank template with CPU, RAM, Network and Storage allocated)
  • XenServer template for Windows 10 (Blank template CPU, RAM, Network and Storage allocated)
  • Windows 2016 ISO expanded to a folder
  • Windows 10 ISO expanded to a folder
  • XenServer PowerShell installed

The first part are all of my parameters

# Parameters

# Name of virtual machines.  Can be more than one, separated by comma
$VMNames = @("Win10-718", "Win10-717")

# PowerShell script to use after OS install completes. Need 1 entry per VMName
$DeploymentScript = @("\\dc1\Automation\VMBuild\InstallVSITarget.ps1", "\\dc1\Automation\VMBuild\InstallVSITarget.ps1")

# Folder to expanded ISO file.
$ImagePath = @("\\media\iso\Win10-1803-Image","\\media\iso\Win10-1803-Image")

# XenServer template with CPU, Memory, network and disk allocated. The disk is empty
$SourceTemplateName = "XS Template - Windows 2016(Blank)"

# Path to the log file
$Logfile = "\\dc1\Automation\VMBuild\VMs"

# Tools used to build an ISO file
$BootFile = "\\dc1\Automation\Software\Oscdimg\"
$ISOTool = "\\dc1\Automation\Software\Oscdimg\oscdimg.exe"

# Active Directory OU to place the VM during the build
$OULocation = "OU=AutoBuildOU,DC=snpp,DC=local"

# XenServer master, user and password
$XenServerHost = "XS2.snpp.local"
$UserName = "root"
$Password = "Chuck Norris"

# Path to the unattended XML file for the OS
$UnattendTemplate = "\\dc1\Automation\VMBuild\AutoUnattendWin2016.xml"

# Unattend.xml variables
$AutoLogonPW = "Chuck Norris"
$AutoLogonAcct = "AutoLogon"
$DomainJoinAcct = "AutoLogon"
$DomainJoinPW = "AutoLogon"
$Domain = "SNPP"
$FQDN = "SNPP.local"
$LocalAdminPW = "Chuck Norris"
$WinProductKey = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"

I have 2 functions that helps with my log file

The first simply gets a data/timestamp for each log entry

function Get-TimeStamp {
    return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)

The second is the log entry. It posts to the screen and to a text file (one for each VM being created)

Function Write-ScreenLog {
    Param ($textstring)

    write-host "$(get-timestamp) : $textstring" -foregroundcolor yellow
    Add-Content -Value "$(Get-timestamp): $textstring" -Path $Logfile\$VMName.txt

Now, we create a VM, 1 loop for each defined VMName


foreach ($VMName in $VMNames) {
    #Prepare Log file. If file does not exist, create. Else, if file exists from previous build, delete and create new file
    If((Test-Path $Logfile\$VMName.txt) -eq $false) {
        New-Item $Logfile\$VMName.txt -type file -force
    else {
        Remove-item $Logfile\$VMName.txt
        New-Item $Logfile\$VMName.txt -type file -force

    Write-ScreenLog "#############################"
    Write-ScreenLog "Creating new VM from ISO file"
    Write-ScreenLog "#############################"

    # Connect to XenServer Pool Master
    Write-ScreenLog "Connecting to XenServer host: $XenServerHost"
    $session = Connect-XenServer -Server $XenServerHost -UserName $UserName -Password $Password -NoWarnCertificates -SetDefaultSession -PassThru

    # Create XenServer VM from blank template
    Write-ScreenLog "Scheduling creation of vm '$VMName' from template '$SourceTemplateName'"
    # Get the source template
    $objSourceTemplate = Get-XenVM -Name $SourceTemplateName
    # Make a copy of the blank template
    Invoke-XenVM -NewName $VMName -VM $objSourceTemplate -XenAction Copy
    # Provision the copy into a VM
    Invoke-XenVM -XenAction Provision -Name $VMName

    # Copy template unattend.xml file to the expanded ISO path
    $ISOPath = $ImagePath[$i]
    Copy-Item $UnattendTemplate -Destination $ISOPath"\AutoUnattend.xml"

    #Customize unattend.xml
    $DefaultXML=Get-Content $ISOPath"\AutoUnattend.xml"
    $DefaultXML | Foreach-Object {
        $_ -replace '1DomainJoinAcct', $DomainJoinAcct `
        -replace '1DomainJoinPW', $DomainJoinPW `
        -replace '1AutoLogonAcct', $AutoLogonAcct `
        -replace '1AutoLogonPW', $AutoLogonPW `
        -replace '1OULocation', $OULocation `
        -replace '1ComputerName', $VMName `
        -replace '1Domain', $Domain `
        -replace '1FQDN', $FQDN `
        -replace '1LocalAdminPW', $LocalAdminPW `
        -replace '1ProductKey', $WinProductKey `
        -replace '1DeploymentScript', $DeploymentScript[$i]
    } | Set-Content $ISOPath"\AutoUnattend.xml"
    Write-ScreenLog "Deployment Script is $DeploymentScript[$i]"

    # Create Custom ISO file VM. This turns the folder that contains the ISO and unattend into a new ISO file
    Write-ScreenLog "Creating bootable ISO called \\media\iso\$VMName.ISO"
    $ISOArg = "-b$bootfile -u2 -h -m -l$VMName $ISOPath \\media\iso\$VMName.iso"
    Start-Process -FilePath $ISOTool -ArgumentList $ISOArg -PassThru -wait

    # Mount Customized OS ISO to VM
    Write-ScreenLog "Mounting customized ISO to $VMName"
    # Get the VM, select the virtual disks that are CD, attach the ISO
    get-xenvm -Name $VMName | select -ExpandProperty VBDs | Get-XenVBD | where {$_.type -eq "CD"} | Invoke-XenVBD -XenAction Insert -VDI (Get-XenVDI -Name $VMName".iso" | Select -ExpandProperty opaque_ref)

    #Start VM
    $VM = Get-XenVM -Name $VMName
    Write-ScreenLog "Scheduling power on of VM '$VMName'"
    Invoke-XenVM -VM $VM -XenAction Start -Async
    $i = $i + 1

Write-ScreenLog "VM creation complete"

A few important things to point out.

I need to customize the Unattend.xml. I start with a template for Windows 10 and another one for Windows 2016. A few entries within the .XML file are variables used to customize the file from the PowerShell script. These include:

  • 1DomainJoinPW
  • 1AutoLogonAcct
  • 1AutoLogonPW
  • 1OULocation
  • 1ComputerName
  • 1DeploymentScript
  • 1Domain
  • 1FQDN
  • 1LocalAdminPW
  • 1ProductKey

The second part is to incorporate this customized Unattend.xml into an bootable ISO file.  Using ETFSBoot and OSCDIMG, I take my folder containing the expanded ISO and unattend.xml and create a customized, bootable ISO file, which I later attach to the VM. The ISO has the same name as the VM because we might have multiple VMs building simultaneously.

When Windows 10 1803 released, I was able to grab the ISO and immediately create a custom VM.

Site Aggregation

At Citrix Synergy, there was a lot of talk about the user’s Workspace; a single location where users get access to all of their resources (apps, desktops, data, devices).

For example, the user’s workspace can include storage apps, SaaS apps, web apps, virtual apps (XenApp), virtual desktops (XenDesktop). Citrix has a cloud service for each one of these resource types, and Workspace integrates all of these services into a single solution for users.

But, what if you already have a fully implemented on-premises XenApp/XenDesktop environment?  What if you have gone through proper design and built an on-premises environment that is stable and scalable? What if you have on-premises expertise and tools to manage and maintain the infrastructure?

Do you have to throw it all away and move your underlying, IT-managed infrastructure into the XenApp and XenDesktop Service within Citrix’s cloud?


Citrix Workspace site aggregation allows you to integrate your IT-managed XenApp/XenDesktop environment.

Take a look to learn how:


Daniel (Follow on Twitter @djfeller)

Citrix Workspace Architecture Poster
XenApp/XenDesktop On-Premises Poster
XenApp/XenDesktop Cloud Service Poster
Citrix XenApp and XenDesktop 7.15 VDI Handbook