Tag Archives: citrix

PowerShell and XenDesktop at the UK PowerShell UserGroup – 4th July 2012

I’ll be presenting tonight for the UK PowerShell UserGroup on using PowerShell to administer your XenDesktop environment. I’ll be providing some info on how the management of XenDesktop is built on top of PowerShell and how to get started using it. Details from Richard’s site below:


Reminder–UK PowerShell UserGroup–July 2012 meeting

When: Wednesday, Jul 4, 2012 8:30 PM (BST)
Where: Virtual


Jonathan Medd will be talking about using PowerShell to administer a XenDesktop environment


Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Unable to join the meeting? Follow these steps:

  1. Copy this address and paste it into your web browser:
  2. Copy and paste the required information:
    Meeting ID: R2TT4R
    Entry Code: Jc-‘8JM;W
    Location: https://www.livemeeting.com/cc/usergroups

If you still cannot enter the meeting, contact support

Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.

Automating the Install of XenDesktop DDC with PowerShell

I had a need to automate the installation of Citrix XenDesktop DDC including using some of the different available install options.

XenDesktopServerSetup.exe is the command line tool to use. Running XenDesktopServerSetup.exe /? displays most of the options that can be used, however I found a couple missing which are documented here.

The Install-XenDesktopDDC function below will enable you to install XenDesktop with different options. For instance, to install all components, but no SQL Express and see the install steps:

Install-XenDesktopDDC -noSQL -Verbose

The installation can be confirmed by checking for the presence of Citrix services:

Get-Service Citrix*

or looking in the installation folder:

To install a subset of components using a specified install media location and a custom install path, this time including the default SQL Express install:

Install-XenDesktopDDC -components "CONTROLLER,DESKTOPSTUDIO" -installMediaLocation "X:\Citrix\XenDesktop\5.6" -customInstallLocation "C:\Citrix"

(Note: I tested the below Install-XenDesktopDDC function with XenDesktop 5.6. It should work with other 5.x versions, but I have not tested those)

function Install-XenDesktopDDC {
Install Citrix XenDesktop Desktop Delivery Controller

Install Citrix XenDesktop Desktop Delivery Controller, with options for different installation types

.PARAMETER components
Specify a comma seperated list of Citrix XenDesktop DDC Components to install

Prevents the installation of SQL Server Express

.PARAMETER installMediaLocation
Specify the location of the Citrix XenDesktop install media, otherwise the CDRom drive is used

.PARAMETER customInstallLocation
Specify the location to install Citrix XenDesktop DDC to

Install-XenDesktopDDC -noSQL

Install-XenDesktopDDC -components "CONTROLLER,DESKTOPSTUDIO" -installMediaLocation "X:\Citrix\XenDesktop\5.6" -customInstallLocation "C:\Citrix"





function Get-CDRomDriveLetter {
	([System.IO.DriveInfo]::GetDrives() | Where-Object {$_.DriveType -eq "CDRom"}| Select-Object -ExpandProperty RootDirectory).Name

function Get-ProcessorArchitecture {
    if ((Get-WmiObject Win32_OperatingSystem).OSArchitecture -eq "64-bit"){
    else {
Write-Verbose "Determining Install Media Location"
if (!$installMediaLocation){
	$CDRomDriveLetter = Get-CDRomDriveLetter
	$processorArchitecture = Get-ProcessorArchitecture
	$installMediaLocation = "$CDRomDriveLetter$processorArchitecture\XenDesktop Setup\"
else {
	$processorArchitecture = Get-ProcessorArchitecture
	$installMediaLocation = $installMediaLocation + "\$processorArchitecture\XenDesktop Setup\"

if (!(Test-Path $installMediaLocation)){
	throw "Path to installation media is not valid"

Write-Verbose "Setting Install Arguments"
if ($customInstallLocation){
	if (!(Test-Path $customInstallLocation)){
	throw "Path to custom install is not valid"
	if ($noSQL){
		$installerArguments = ('/QUIET','/INSTALLDIR',$customInstallLocation,'/COMPONENTS',$components,'/CONFIGURE_FIREWALL','/NOREBOOT','/NOSQL')
	else {
		$installerArguments = ('/QUIET','/INSTALLDIR',$customInstallLocation,'/COMPONENTS',$components,'/CONFIGURE_FIREWALL','/NOREBOOT')
else {
	if ($noSQL){
		$installerArguments = ('/QUIET','/COMPONENTS',$components,'/CONFIGURE_FIREWALL','/NOREBOOT','/NOSQL')
	else {
		$installerArguments = ('/QUIET','/COMPONENTS',$components,'/CONFIGURE_FIREWALL','/NOREBOOT')

Write-Verbose "Running the XenDesktop Installation"
Push-Location $installMediaLocation
Start-Process -FilePath XenDesktopServerSetup.exe -Wait -ArgumentList $installerArguments

Citrix XenDesktop 5 Training from TrainSignal

I had a, shall we say urgent, need to get up and running with Citrix XenDesktop 5 in a very short space of time. Having used some of the TrainSignal products before  and had a very good experience with them my first thought was to head over to their site and see if they had anything available. Thankfully, they have courses for both XenDesktop 4 and 5 so I was able to get hold of the XenDesktop 5 course. As with all the other courses you get both online access and a DVD with formats suitable for desktop / laptop and smartphone / tablets. (In this instance I only had online access, however was able to successfully stream the entire course to an iPad on 3G while on train journeys)

The topics covered on the course are listed below. Lessons 5 – 13 were those that I initally needed to get through quickly so focused on those and found that they covered well the significant part of what I needed to know.

Citrix XenDesktop 5 Training – Course Outline

Lesson 1 – Getting Started with Citrix XenDesktop 5 Training
Lesson 2 – Lab Setup
Lesson 3 – The Course Scenario
Lesson 4 – Introduction to Desktop Virtualization
Lesson 5 – Planning Provisioning Server Deployment
Lesson 6 – Installing and Configuring Provisioning Server
Lesson 7 – Creating vDisks and Configuring Target Devices
Lesson 8 – Managing vDisks, Target Devices, Servers and Printers
Lesson 9 – Configuring Provisioning Server High Availability
Lesson 10 – Planning XenDesktop 5 Deployment
Lesson 11 – Installing and Configuring XenDesktop 5 – Part 1
Lesson 12 – Installing and Configuring XenDesktop 5 – Part 2
Lesson 13 – Managing XenDesktop 5
Lesson 14 – Monitoring and Troubleshooting XenDesktop 5
Lesson 15 – Working with Citrix Receiver
Lesson 16 – Working with Profile Manager
Lesson 17 – Upgrading from XenDesktop 4
Lesson 18 – Preparing for the Citrix XenDesktop 5 Administration (A19) Exam
Lesson 19 – Next Steps

Citrix XenDesktop 5 Training – Bonus Lessons

Lesson 20 – Configuring NetScaler Access Gateway Enterprise Edition
Lesson 21 – Working with XenDesktop Setup Wizard

I’ve subsequently been through most of the rest of the lessons and found that it gives you excellent coverage of the XenDesktop product. I enjoyed Elias’ style of training; good explanations and he is always very positive about each lesson and the product itself.

The only thing I think is possibly missing from the course is that it would be worth a lesson on the XenDesktop PowerShell snapins. Since the entire management of the product is built on top of PowerShell it is worth knowing at least how to get started with this topic, even if you are using the GUI to demonstrate the rest of the training. An introduction to how to get started with the PowerShell snapins and a few basic examples would be a useful addition.

If you have a need to learn about XenDesktop then I would highly recommend that you consider using this course. I think TrainSignal have put themselves in a good place providing these two courses since in terms of book availability (which you could either view in terms of competition or complimentary) there are not many tech books available on this subject, although I notice that Elias has ‘Mastering Citrix XenDesktop‘ scheduled to come out later this year.

PowerShell Quick Tip: Converting a String to a Boolean Value

Some PowerShell cmdlets include switch parameters, i.e. no arguments are typically supplied to them – they are either True / On when they are present and False / Off when they are not. However, it is also possible to explicitly specify them with $true and $false, e.g.

-switchparameter:$true  or


Typically you would not use this when working manually at the console, but what if you needed to automate a task using a switch parameter and set it to be On or Off based on values from a CSV or XML file, i.e. you supply the true or false as a string?

This can lead to some initially confusing behaviour; look at this example.

$persistent = “False”


PowerShell appears to have converted our ‘false’ string to a Boolean ‘true’, not what we were expecting! This is because PowerShell will convert any string greater than 0 characters to a Boolean ‘true’, behaviour which is consistent across other programming languages.

So there are a couple of ways round this, either change your data to an empty string (which may not be possible of course)….

$persistent = “”


or use the .Net System.Convert ToBoolean method:

$persistent = “False”


Looking at a practical example of how you might use this take a look at working with one of the Citrix XenDesktop providers to create a Hypervisor Connection (more on this topic to come)

New-Item -Path xdhyp:\Connections –Name $Name –HypervisorAddress $HypervisorAddress –UserName $UserName –Password $Password –ConnectionType $ConnectionType –Persist: ([System.Convert]::ToBoolean($persistent))

A more detailed explanation of this topic is well written up by Kirk Munro


Monitor Citrix License Usage With PowerShell

WMI in Windows Server is a treasure trove of information and well worth investigating, particularly when needing to run reports against many servers. In addition it is possible for third-parties to make use of WMI and store their own information in there. This is true of a recent requirement I had to monitor Citrix Licensing.

Whilst it’s obviously critical to purchase enough licenses for Citrix that you need, its also important to not have too many lying around not in use, since you’ll be wasting money.  Given that Citrix Licensing is based on concurrency you may have different usage patterns at the time of day, month or year.

Contained within the WMI Namespace ROOT\CitrixLicensing is a class Citrix_GT_License_Pool. In this class you can find details for registered licenses and how many are in use. The PowerShell cmdlet Get-WMIObject can be used to retrieve this information. Once you have it you could save the report into a CSV file, write an entry to an event log or send an email alert.

The below example will generate an email alert when then level of licenses in use goes over 90%. The email will contain basic details of how many licenses are currently in use.

 Report on Citrix License Usage
 Report on Citrix License Usage
 Authors:Jonathan Medd
.PARAMETER CitrixLicenseServer
 Name of Citrix License Server
 Get-CitrixLicenseUsage -CitrixLicenseServer Server01
param (
 [parameter(Mandatory=$True,HelpMessage='Name of Citrix License Server')]

# Get Citrix Licensing Info from WMI
$LicensePool = Get-WmiObject -class "Citrix_GT_License_Pool" -Namespace "ROOT\CitrixLicensing" -ComputerName $LicenseServer

# Calculate licenses in use, total number of licenses and percentage currently in use
$InUseNum = ($LicensePool | Measure-Object -Property InUseCount -sum).Sum
$InstalledLicNum = ($LicensePool | Measure-Object -Property Count -sum).Sum
$PercentageNum = [math]::round(($InUseNum/$InstalledLicNum)*100,2)

# Check the usage and send an email if over 90%
if ($PercentageNum -lt 90)
Send-MailMessage -To "[email protected]" -Subject "Citrix License Server Statistics For $CitrixLicenseServer" -Body "The below is the current status of the license server:`n`nInstalled Licences: $InstalledLicNum`n`nLicences In Use: $InUseNum`n`nPercentage: $PercentageNum%" -SmtpServer "smtpserver" -From "[email protected]"


Running Outlook 2003 in TS or Citrix and Planning an Upgrade to Exchange 2010?

Outlook 2003 is listed as a supported client for Exchange 2010 with the following caveats:

  • Clients running Outlook 2003 don’t use RPC encryption, which RPC Client Access requires by default. You will either need to turn off the RPC encryption requirement or configure Outlook 2003 to use RPC encryption. However, Outlook 2007 and later versions are automatically compatible with the change to RPC Client Access because they support RPC encryption by default. For more information, see Understanding RPC Client Access.
  • On clients running Outlook 2003, you may notice that folder updates don’t occur automatically in a timely manner. This situation occurs because User Datagram Protocol (UDP) notifications aren’t supported in Exchange 2010. For more information about resolving this issue, see Knowledge Base article 2009942, In Outlook 2003, e-mail messages take a long time to send and receive when you use an Exchange 2010 mailbox. However, Outlook 2007 and Outlook 2010 are automatically compatible with this change.

Having now witnessed the impact of the second issue it could cause you a big issue if you are running Outlook 2003 in Terminal Services or Citrix. The KB article 2008842 suggests two options:

  • Make a registry interval to reduce the polling time from 60 seconds to a lower value, 10 is the minimum
  • Use Outlook’s Cached Exchange mode

Having made the registry change down to 10 seconds the phrase from above ‘…..folder updates do not occur in a timely manner’ is pretty diplomatic! I think most people could live with an email sitting in the Outbox for a few seconds or being delivered within seconds rather than instantaneously. However, deleting an email and it then not dissapearing for up to 10 seconds is a real issue. It feels like it didn’t work, so naturally you press the delete key again and this time you are presented with an error because that item no longer exists. The whole experience with this refresh issue is pretty poor.

Whilst Outlook’s Cached Exchange mode is a very common deployment method for laptops and desktops (if not the standard these days) you cannot use it when running Outlook 2003 in Terminal Services or Citrix.

The final option is an upgrade to Outlook 2007 / 2010 which might not be a big deal in some organisations, in others it will involve significant work and planning.

It appears that there is unlikely to be a better fix either. Further details already written up very well here.

Update 05/11/2010

The KB article has been updated to reflect the fact that the minimum value can actually be set to 5 seconds not 10. Whether that is an acceptable value for your environment is another matter.

Update 01/02/2010

So it looks like enough customer pressure has been placed and the Exchange Team have just announced that UDP support for Outlook 2003 will be available for Exchange 2010 in Roll-up 3 for SP1. This means you can now consider Outlook 2003 in Terminal Services as a viable client for Exchange 2010 again.

Virtualising Citrix on VMware

I was lucky enough to take on a project initially started and blogged about by my co-host on the Get-Scripting podcast Alan Renouf.

In summary, his posts were mainly around the design decision of whether to go for VM’s with one or two vCPU’s and how many Citrix users you could support per VM.  Following on from his initial testing using Citrix Edgesight we ran a pilot with a few different scenarios and it turned out that the best performance with the highest number of Citrix users per VM came out to be a VM with 2 x vCPU’s; a conclusion which didn’t really match the initial testing, I guess you can’t beat real users doing real work and the sometimes crazy things they get up to pushing the boundries of performance.

A number of other decisions were also made at this time, most of which contributed to other significant cost savings on top of those we were going to achieve simply by reducing the number of physical boxes used to host the Citrix environment.

Something else which came out of the pilot was a decision to store the VM’s on local storage not SAN. Whilst this obviously reduces the flexibility offered by a virtualisation solution with shared storage, which gives options like VMotion, DRS etc, the cost savings gained by using local storage were very significant. Not only did we have none of the charges associated with SAN storage (fibre cards, cabling, switch ports, SAN disk) we could deploy the hosts with ESX Foundation licenses. From a redundancy and maintenance point of view we designed it so that we could afford to lose more than one host for a period of time and still have enough capacity to provide a good service.

We deployed four VM’s per ESX host, i.e. 8 cores available to 8 x vCPU’s. (Note: I have recently read Duncan Epping’s post around how many cores you should specify when using CPU affinity. It makes for interesting reading, thankfully we are not currently seeing any issues around what might arise from this)

During the pilot and the early part of the rollout we found we were able to happily achieve around 45 users per VM, i.e. up to 180 per ESX host with CPU levels on the host comfortably averaging below the 75% mark. As the rollout progressed and we retired the physical Citrix boxes the levels attracted by each VM were more typically around the 40 users mark, i.e. approx 160 users per physical host.

This was because we were able to replace three physical Citrix boxes with one ESX host containing four Citrix VM’s, so a 3 – 1 reduction physical, but a 25% increase in the number of Citrix servers which obviously means you naturally attaract less users per Citrix server with a consistent number of users.  However, since we deployed 2 x vCPU machines it also meant cost savings with half the required Windows VM’s over the original plan to deploy 1x vCPU VM’s which would have meant eight Citrix VM’s per host.

One issue we did experience was that of vCPU peaks from rogue user processes which would hog all the CPU for significant periods of time and give a bad experience to other users on that VM. This was believed to happen previously in the physical Citrix deployemnt, but was more easily masked by the availability of physical cores. Most typically these processes would be Internet Explorer, quite often accessing Flash based content. To mitigate this issue we used some application threading software on each VM to set maximum levels for CPU usage per user process. This performed very well by limiting these processes to a certain amount of vCPU and consequently not impacting other Citrix users’ performance – the decision to use 2 x vCPU’s in a VM helped here too, the 1x vCPU VM’s in the pilot really suffered with this problem.

Counting the Number of Sessions Per Citrix Server

Whilst monitoring some newly provisioned Citrix servers running on VMware hosts today, I soon became very bored with manually checking how many sessions were on each Citrix VM as the load on each one increased, whilst trying to get it to the optimum level.

I knew it was possible to use Powershell to connect with Citrix servers, but had never really looked into it before. Not surprisingly it turned out to be very straightforward.

By using some technology known as MFCom we can connect with the Citrix farm and get some cool information out.

In the below example we create a new com object using MFCom, then initialise the connection. We are then able to access some methods and properties of that object. In this case we are looking at the Sessions property, we group all of the results by ServerName and then produce some output with the name and number of sessions on that Citrix box.

$farm = New-Object -com "MetaframeCOM.MetaframeFarm"$farm.Initialize(1)$farm.Sessions | Group-Object ServerName | Sort-Object name | Format-Table Name,Count -auto

which will give you something like:

Name Count

CitrixServer01 38
CitrixServer02 45
CitrixServer03 41

This would return all of the servers in the farm. In this particular instance I only wanted a particular selection of servers, so I stored them in a text file, got PS to read that file and then filter the query by only looking at servers in that list.

$servers = Get-Content c:\scripts\servers.txt

$farm = New-Object -com "MetaframeCOM.MetaframeFarm"$farm.Initialize(1)$farm.sessions | Where-Object {$servers -contains $_.ServerName} | Group-Object ServerName | Sort-Object name | Format-Table Name,Count -auto

Once again Powershell very easily gets rid of a really dull manual task.

If you wish to take this a step further check out Powershell MVP Brandon Shell’s blog where he has loads of Powershell / Citrix examples.