Hello all, my name is Travis Howe and I’m a developer on the Remote Desktop Virtualization team. One of the new features that we’re all very proud of in Windows Server 2012 is a new Windows PowerShell layer, which provides a powerful set of functionality to set up, configure, and control your Windows Server 2012 Remote Desktop Services (RDS) deployments. The feature is too big to cover in one post, but I wanted to give you a quick introduction to help you get started with scripting your deployments in the Windows Server 2012 Release Candidate build. In this post I’ll give a brief overview of the kinds of tasks you can perform by using the new RDS Windows PowerShell layer, and then go a bit more in-depth with one of the Windows PowerShell cmdlets that you’ll likely be using a lot in your scripts (Get-RDServer), and finally finish up with a practical example showing how to use that cmdlet to install the Desktop Experience feature on all of the Remote Desktop Session Host (RD Session Host) servers in your deployment.
To keep this introduction focused on the RDS functionality enabled by our new Windows PowerShell layer, I’ve written this post assuming you have a basic understanding of Windows PowerShell. If you’d like to learn more about Windows PowerShell, a few good places to start are this page on the TechNet Library http://technet.microsoft.com/en-us/library/bb978526.aspx and the Windows PowerShell Blog at http://blogs.msdn.com/b/powershell/.
The first step in using the new RDS Windows PowerShell layer in Windows Server 2012 is to load the RemoteDesktop module (using the command import-module RemoteDesktop). This module contains all the new RDS cmdlets. Broadly speaking, the cmdlets in this module can be broken up into the following feature areas:
You’ll be hearing more about these feature areas in the coming months. For now, let’s focus on just one of the cmdlets meant for managing your deployment: Get-RDServer.
Figure 1: The Get-RDServer cmdlet
PS C:\windows\system32> import-module RemoteDesktop PS C:\windows\system32> Get-RDServer -? NAME Get-RDServer SYNTAX Get-RDServer [[-ConnectionBroker] <string>] [[-Role] <string[]> {RDS-VIRTUALIZATION | RDS-RD-SERVER | RDS-CONNECTION-BROKER | RDS-WEB-ACCESS | RDS-GATEWAY | RDS-LICENSING}] [<CommonParameters>]
As you can see in figure 1, the cmdlet takes two parameters: ConnectionBroker, and Role.
The ConnectionBroker parameter is an optional parameter for many of the cmdlets in the RemoteDesktop module. This is used to specify the FQDN of the server running the RD Connection Broker role service for the deployment (in a high availability deployment, use the FQDN of the RD Connection Broker server that is running the active instance of the Remote Desktop Management Server service. You can control which RD Connection Broker server is running the active instance by using the Set-RDActiveManagementServer cmdlet).
The Role parameter is used here to narrow down which of the RDS roles you are interested in:
You can specify one or more of these roles to narrow your results, or you can omit the parameter entirely to return all servers in your deployment.
When run, the cmdlet returns one or more objects of type Microsoft.RemoteDesktopServices.Management.RDDeploymentServer. These objects will contain two properties:
Now, I’ll demonstrate how to use this cmdlet in a real-world example.
Using the Get-RDServer cmdlet in conjunction with a few useful cmdlets from the ServerManager module, we can write a fairly simple script that allows us to enumerate all of the RD Session Host servers in our deployment, and then install the Desktop Experience feature on any servers that do not already have it installed. In a real deployment this would allow your end users to take advantage of the full Windows 8 client experience in their remote sessions.
For brevity, only the “meat” of the script will be presented here. The full script is available on the TechNet Script Center for download at http://gallery.technet.microsoft.com/scriptcenter/Install-Desktop-Experience-ae573c09
First, some setup code:
Figure 2: Script lines 1-13
1 [CmdletBinding(SupportsShouldProcess=$true)] 2 param ( 3 [Parameter(Mandatory=$false)] 4 [string] 5 $ConnectionBroker, 6 7 [Parameter(Mandatory=$false)] 8 [switch] 9 $Force 10 ) 11 12 import-module ServerManager 13 import-module RemoteDesktop
As you can see in figure 2, our script takes two parameters: ConnectionBroker, and Force. The ConnectionBroker parameter will be passed-through to the Get-RDServer cmdlet as described in the previous section. I won’t go into the Force parameter in this post—briefly, it is used to suppress confirmation prompts. For more information, see the full script on the Script Center.
Also in figure 2, we import two key modules: the ServerManager module, which gives us the cmdlets necessary to control the installed features, and the new RemoteDesktop module, which will let us determine the list of RD Session Host servers in our deployment.
Next, we’ll fetch the list of RD Session Host servers in the deployment:
Figure 3: Script lines 15-24
15 # Fetch all RDSH servers in the deployment 16 $sessionHosts = Get-RDServer -Role RDS-RD-SERVER –ConnectionBroker $ConnectionBroker -ErrorAction Stop 17 if(-not $sessionHosts) 18 { 19 Write-Error "No RD Session Host servers found in the deployment" 20 return 21 } 22 23 $sessionHostsString = $sessionHosts.Server -Join ", " 24 Write-Verbose "Discovered session hosts: $sessionHostsString"
In figure 3 we use the new Get-RDServer cmdlet to retrieve a list of objects representing servers in the deployment that have the RDS-RD-SERVER role (a.k.a. the RD Session Host role) installed. We then write the list of discovered RD Session Host servers to the verbose output (useful in case we need to debug the script down the road).
Next, we’ll check if any of the RD Session Host servers already have the Desktop Experience feature installed:
Figure 4: Script lines 26-51
26 # Determine which ones don't have desktop experience installed 27 $toInstall = New-Object System.Collections.ArrayList 28 foreach($rdsh in $sessionHosts.Server) 29 { 30 try 31 { 32 $desktopExp = Get-WindowsFeature -Name Desktop-Experience -ComputerName $rdsh -ErrorAction Stop 33 34 if($desktopExp.Installed) 35 { 36 Write-Host "The Desktop Experience feature is already installed on $rdsh" 37 } 38 elseif($desktopExp.InstallState -ne [Microsoft.Windows.ServerManager.Commands.InstallState]::Available) 39 { 40 Write-Warning "Cannot install the Desktop Experience feature on $($rdsh): the feature does not appear to be available for installation, the InstallState is listed as '$($desktopExp.InstallState)' instead of 'Available'" 41 } 42 else 43 { 44 $toInstall.Add($rdsh.ToLower()) | Out-Null 45 } 46 } 47 catch 48 { 49 Write-Warning "Cannot install the Desktop Experience feature on $($rdsh): error querying Desktop Experience feature: $_" 50 } 51 }
In figure 4 we loop over the list of RD Session Host servers, and use the Get-WindowsFeature cmdlet to determine whether the Desktop Experience feature is already installed, not available for installation, or available to be installed. For all the servers where the feature is available to be installed, we add them to a list for further processing.
I’m going to skip lines 54-93 here because they contain fairly simple code for edge-case handling and prompting the user for confirmation. For details, see the full script on the Script Center.
Finally, we can install the feature on the selected RD Session Host servers:
Figure 5: Script lines 94-99
94 # Install the feature 95 foreach($rdsh in $toInstall) 96 { 97 Write-Verbose "Installing Desktop-Experience on machine $rdsh" 98 Install-WindowsFeature -Name Desktop-Experience –Restart -IncludeAllSubFeature -IncludeManagementTools -ComputerName $rdsh 99 }
And that completes our script: we’ve gathered the list of RD Session Host servers by using the new Get-RDServer cmdlet, and with the help of some commands from the ServerManager module, made sure that the Desktop Experience feature is installed on all of them.
I hope this introduction has been helpful. There’s a lot of functionality in the new RemoteDesktop module, so I encourage you to dive in and start scripting your deployment!
Excellent stuff!
Great article, good example scripts!
Kind regards,
Freek Berson
themicrosoftplatform.com
How do you create a new RDP Listener in Server 2012?
Hey Travis,
Win32_ServerFeature class has been deprecated. This class works for Win2k8 R2 and below.
Can you tell us how to enumerate the windows 2012 server feature programmatically?
Thanks
Irfan
Hi Irfan,
Good catch, thanks for letting me know. I'll investigate and update here as soon as I can.
Thanks,
Travis
Hi all,
I wanted to follow-up on my last comment. I've verified that Win32_ServerFeature is deprecated in Server 2012. It looks like the replacements are the Server Manager cmdlets: technet.microsoft.com/.../ee662311.aspx
I will update the sample script and blog post contents to use these cmdlets as soon as I can find some time.
Cheers,
is there a way to use scripts so we can RDS work in a workgroup environment
humm...
Where do I put a recomendation for a printable version?!?