Server 2012 Automating Remote Desktop Install

Posted by

In this guide we will be showing you how to install and implement a fully redundant remote desktop session host environment running on Server 2012.

We will be showing you how to make use of Hyper-V, System Centre Virtual Machine Manager, Orchestrator Service Manager to make a fully automated install of all your session host servers, giving you the ability to easily scale out your RDSH servers to support growing needs, as well as making it much simpler to rebuild the entire RDSH farm by logging a service request in Service Manager. We can further go ahead and rebuild RDSH servers by linking them into SCOM, so for example a failed server could automatically be rebuilt, or if the load is to heavy we can provision a new one.


I’ll break this down into smaller sections that you can follow through.


To set the environment we are using Hyper-V 2012 clusters running on HP Hardware. The estate is managed by Virtual Machine Manager 2012 SP1, Orchestrator 2012 SP1 and Service Manager 2012 SP1. The remote desktop servers are all virtual Server 2012 Enterprise servers.


We won’t go through in-depth configuration steps for the environment, as this is more an overview of the settings and process required to accomplish a fully automated remote desktop farm.


Server installation


To provide a fully resilient infrastructure for Remote Desktop Session Host you will need the following servers, physical or virtual is fine:

  • 2 x Connection Brokers (these servers distribute the load amongst the RDSH servers) (SV-RDCB01 / SV-RDCB02)
  • 2 x Web and Gateway servers (these servers sit in the DMZ environment and run IIS as well as the remote desktop gateway)(SV-RDWEB01 / SV-RDWEB02)
  • 2 x Licence Servers (these can run on any 2012 servers – they don’t need to be dedicated for this purpose) (SV-INFR05 / SV-INFR06)
  • 1 x Session host server (this server must be virtual running on Hyper-V with virtual centre in place) (SV-RDSH01)


1. Prebuild all the servers with a vanilla instance of Server 2012, then from your client launch Server Manager and add all the servers that are going to be provisioned in the remote desktop farm.


2. From Server Manager add the Remote Desktop Services Installation Role and select Standard Deployment


Select ‘session-based desktop deployment’

And go through and add the relevant servers to the pool. You can’t setup any failover / redundancy during this part so just select the SV-RDCB01 for the connection broker, SV-RDWEB01 for the web server and SV-RDSH01 for the remote desktop server.

Once the install is complete and the servers have rebooted if appropriate we are ready to start configuring them.


The first thing to do is install all your applications on the remote desktop server. We will be making a clone of this server and converting it to a template in SCVMM later. Be aware that some applications may not like this cloning process as the machine will be syspreped before. Be sure to test all your applications thoroughly.

Now all your applications are installed you can install the remaining servers to make them redundant.

Connection Broker

From the Remote Desktop Deployment Overview screen, right click RD Connection Broker Icon and select Add RD Connection Broker Server


Follow through the wizard to add the new connection broker selecting SV-RDCB02 as your server.

Then follow the steps provided in this blog article to configure highly available connection brokers

When specifying the DNS name, if your plan is to use publically generated certificates (such as VeriSign) then make sure you use the same name that will be given the certificate otherwise your clients will get a certificate warning.


Web and Gateway Servers

If you are having external users connect in to your remote desktop environment you will need to install the gateway servers and web servers in a DMZ environment. They need to be domain joined. We configure these with windows network load balancing. External access is accomplished over TCP443 HTTPS connections. You will need a certificate issued to these servers with the subject being the NLB name. This should be a publically resolvable internet DNS name.

Installing and configuring the servers is a wizard driven process. Configure the NLB first, then add the additional server through server manager and add it to the NLB cluster.


Licence Servers

If you don’t currently have RDP licences you get a free eval trial for 120 days which allows you to use all the features without a licence. If you have purchased licences, simply install the role through Server Manager on the servers you are using for licencing and then configure the licence using the licence manager snapin. In server manager you can configure your preferred order that the licence servers are used.


RDSH Collections

Server 2012 remote desktop sessions work with collections. A collection is a set of RDSH servers which work together. To create a new collection, from server manager, right click RD Session Host and select ‘create session collection’




Follow the steps in the wizard to create a new collection, adding the only RDSH server you have. Most of the default options are sufficient but feel free to change them to suit.


You should now have configured a redundant remote desktop environment with the exception of the remote desktop session host server.

Configuring automation

Cloning the RDSH Server

You now are ready to convert your Remote Desktop Session Host Server to a template in SCVMM. We recommend you take a clone of the RDSH server prior to doing this as converting to a template will destroy the original virtual machine.

When you run the convert to template wizard, it first runs sysprep to generalize the image. This allows the template to be deployed to a new virtual machine. You could at this stage deploy a new VM from the template, join it to AD and add it to the collection manually. This would work fine, but we want a fully automated process. This is where Service Manager, Orchestrator, SCVMM and PowerShell come in.


Service Manager

(This section is courtesy of my colleague James Yeomans who looks after our service manager and orchestrator environment with my help on the scripts)

In Service manager we have created a new incident template to create a new RDSH server. This makes it easy for us to create a new server from a service request.





We don’t actually need to specify any information in the incident as it’s all configured in the template. There is an Orchestrator runbook linked to to the incident. We can chose to put a user in the affected user field and they will receive an email progress report when the server built is complete.

The Request Offering is called “New RDSH Server Required”. It is this Request Offering that the portal links to. There is just one mapped field which is called Description and maps to the Description field in the Incident.



The orchestrator run book is configured with the following steps:




INITIALIZE DATA: This is simply passed the Incident ID from SCSM to a variable called “Incident ID”


GET INCIDENT: This takes the Incident ID from the Initialize Data Step and retrieves the Incident from SCSM.


GENERATE COMPUTER NAME: This step runs a PowerShell script to check AD for the highest number RDSH Server. It then returns a variable called “newname” with the next highest name. This will be the new computer name.

(Our naming convention for RDSH servers follows the format of SV-RDSH01 – 02 – 03 etc, so we needed a way to generate a new name based on the next available server name. This was accomplished using this script.


   1: #Finds the next available computer name


   3: #Import Modules

   4: Import-Module "C:\Program Files\Quest Software\Management Shell for AD\Quest.ActiveRoles.ARSPowerShellSnapin.dll"

   5: Connect-QADService


   7: #Variables

   8: $servernamePrefix = "SV-RDSH"


  10: #get the current list of computer names in AD matching the server name prefix

  11: $currentServerName = Get-QADComputer $servernamePrefix

  12: $currentServerName = $


  14: #remove the words sv-rdsh from the server name to just leave the number suffix

  15: $currentserverNameSuffix = $currentServerName -replace "SV-RDSH"


  17: #find the highest number from the list of servers

  18: $currentservernamesuffix = $currentServerNamesuffix | measure -Maximum


  20: #set the current servername value to the number of the highest server    

  21: $currentservernamesuffix = $currentServerNamesuffix.Maximum



  24: #add a value of 1 to the server number value

  25: $newservernamesuffix = $currentServerNamesuffix + 1



  28: #Check to see if the server name suffix is a single integer


  30: if ($newservernamesuffix -le "9") {

  31:     $newServerNamesuffix = "0$newServerNamesuffix"

  32:     }


  34: #Compile the new servername

  35: $newServerName = "$servernameprefix$newservernamesuffix"


  37: #Display the new servername


  39: return $newServerName




PRE-STAGE Computer: This creates an AD computer account with the name contained in the newname variable from the previous step. The AD account is created at this point incase multiple versions of this runbook are running at the same time they would otherwise try to use the same computer name which would cause a failure.


CHOOSE STORAGE: This is a PowerShell script that queries the Hyper-V cluster for the CSV with the highest % free space and returns the path of the CSV as a variable called “csv”. This makes sure that we aren’t going to chose a bad CSV for storage. The script will be adapted later on to stop the run book if the amount of free space left is not enough to create the VM. The script is an edited version of the script provided on technet.

   1: #Import modules

   2: Import-Module FailoverClusters


   4: #Setup variables

   5: $objs = @()

   6: $cluster = "CLU-SV-VHCC"


   8: #Gets the cluster shared volumes from the cluster and their associated properties

   9: $csvs = Get-ClusterSharedVolume -Cluster $cluster

  10: foreach ( $csv in $csvs )

  11: {

  12:    $csvinfos = $csv | select -Property Name -ExpandProperty SharedVolumeInfo

  13:    foreach ( $csvinfo in $csvinfos )

  14:    {

  15:       $obj = New-Object PSObject -Property @{

  16:          Path        = $csvinfo.FriendlyVolumeName

  17:          PercentFree = $csvinfo.Partition.PercentFree

  18:       }

  19:       $objs += $obj

  20:    }

  21: }


  23: #Selects the CSV with the most free space as a %

  24: $mostfree = $objs |  Sort-Object -property PercentFree -Descending | Select-Object -First 1


  26: #Outputs the path to the csv with the most free space as a %

  27: $mostfree.path





CREATE VM FROM RDSH TEMPLATE: This step creates the VM in SCVMM. It takes the CSV and the name as variables from the previous steps.


GET NEW COMPUTER INFORAMTION: This step gets the new computer account from AD by using a filter where the common name of the computer matches the new vm name. This step is required for the next step which moves the computer to a different OU.


MOVE COMPUTER TO CORRECT OU: This takes the DN of the computer obtained in the previous step and moves that computer to the RDSH2012 OU in AD.

(this makes sure the server goes in the correct OU so any session host group policies apply to the server)


START NEW VM: This takes the VM ID from the machine that was created and starts it.


JOIN RDS FARM: This runs a script on the new machine that logs an event on the new server. This starts the process of joining the machine to the RDS Farm.

(It seemed the cleanest way of running the PowerShell script on the remote desktop server to join it to the RDS Farm and Collection. The Remote Desktop powershell commands need administrative rights to run the commands. We acocmplished this by using a scheduled task configured in the GPO applied to RDSH servers. The scheduled task was activated on the generation of a specific event ID in the logs. So all we need to do from orchestrator is run the powershell command to generate that event ID.)


   1: write-eventlog -computer localhost -logname application -source "RemoteDesktopScript" -eventID 59128 -entryType Information -message "Script request initiated" -category 1 -rawdata 10,20


We already setup the new event log as part of the remote desktop group policy using a startup PowerShell script which contains the line

   1: new-eventlog Application RemoteDesktopScript


This 59128 eventID we log causes the task to run this PowerShell script



   2: #Imports the Remote Desktop powershell module

   3: Import-Module RemoteDesktop


   5: #Script Variables

   6: $role = "RDS-RD-Server"

   7: $ConnectionBroker = ""

   8: $Collection = "AML Applications"

   9: $log = "\\server\services$\LogFiles\RDP\rdp.txt"



  12: #Start log file


  14: Add-Content $log "Selected server role is $role"

  15: Add-Content $log "Selected connection Broker is $connectionbroker"

  16: Add-Content $log "Selected collection is $collection"


  18: #Gets the current FQDN and hostname of the server

  19: $ipProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()

  20: $fqdn = "{0}.{1}" -f $ipProperties.HostName, $ipProperties.DomainName

  21: $hostname ="{0}" -f $ipProperties.HostName

  22: Add-Content $log "Server hostname is $hostname, server fqdn is $fqdn"


  24: #Adds the new server to the remote desktop pool

  25: Add-RDServer -Server "$fqdn" -Role "$role" -ConnectionBroker "$connectionbroker"



  28: #Adds the new server to the session hosts collection

  29: Add-RDSessionHost -SessionHost "$fqdn" -CollectionName "$collection" -ConnectionBroker "$connectionbroker"


  31: #Write errors to log file

  32: Add-Content $log "$Error"

RESOLVE INCIDENT: This takes the Incident ID from the Get Incident step and resolves it.


CLOSE INCIDENT: This takes the Incident ID from the Get Incident Step and closes the Incident.



There you have it, a fully automated deployment of a new RDSH server that automatically joins your collection and is usable immediately by your clients.