Managing Remote Desktop services (aka Terminal services) using Windows PowerShell

PowerShell Team

Hello everyone,

We are pleased to announce that the Beta release of Windows server 2008 R2 supports managing Remote Desktop services using PowerShell.  You can now configure and manage all RDS role services and components using PowerShell.  For example, below are few management tasks that you can now do with PowerShell

1.       View and edit configuration settings of Remote Desktop server

2.       Publish RemoteApp applications

3.       Configure License Server

4.       Create and configure a Remote Desktop server farm

5.       Configure and assign virtual IP addresses to either sessions or applications

6.       Create and manage RDV (VDI) pools

7.       Create and manage Gateway Resource Access & Client Access policies

Of course there is a lot more that you can do with Windows PowerShell. Install the beta release of Windows Server 2008 R2 and give this feature a try. As always, we are eager to hear what you think and it is important that you let us know what you like and don’t like as early as possible.

Read further to understand RDS PowerShell in detail.

Remote desktop services PowerShell

Once you install the Remote Desktop services role, a PowerShell provider gets installed. This Provider (we’ll call it RDS provider in the rest of this post) allows you to view and manage the configuration of all role services and components of Remote Desktop Services.

 Think of RDS Provider as something similar to file system provider and registry provider, IIS Provider. You view, navigate and work with RDS provider as you would with any of the other providers.

 Working with RDS PowerShell

To get started, first install the Remote Desktop services role and then launch RDS PowerShell.

Step 1: Install Remote Desktop services role

RDS PowerShell is installed when you install the Remote Desktop services role. You can install the Remote Desktop services role using Server Manager. 

Step 2: Launch RDS PowerShell

Right click on Start Menu -> All Programs -> Administrative Tools -> Remote desktop services -> ‘Remote Desktop Services PowerShell’ and select ‘Run as Administrator’.

Once you click on this link, you’ll see a PowerShellPowerShell window with the prompt set to RDS drive. There it is – the RDS provider for you.

You’d notice that once you issue the dir command, you see a view that has the following six columns.

Name: Name of the Container/Setting

Type: Type of Item. There are three possible values for Type – Container (Node), Integer, or String. Container (Node) denotes a Container Item, and Integer and String denote Settings. You can only CD into container items. Containers represent a setting group or a logical entity whereas Settings represent configuration settings. For example, roles such as RDS andConnection broker, and entities such as Connection Objects and RemoteApps are represented as Containers, while server drain mode is represented as a setting

CurrentValue: Value set to the Item (applicable only toItems of ‘Integer’ or ‘String’ Type)

GP: Indicates whether an Item is controlled by group policy or not

PermissibleValues: Possible values that a Setting Item can have

PermissibleOperations:  Operations (cmdlets) that can be performed on the Item

Users can select which columns are displayed by using the Format-table cmdlet. For example  Get-Item * | format-table -Property Name, CurrentValue displays only Name and CurrentValue columns. Alternatively you can use dir * | ft -Property N*,C* to achieve the same result. 

You can also customize the default view. More on this in a later post.

How to get help?

One of the salient features of PowerShell is that it makes it easy to get information and help on a particular aspect. That advantage is retained in RDS Provider as well. There is a property called Description associated with every Item which succinctly describes what a particular setting does.

For example PS RDS:\RDSConfiguration> get-item .\DrainMode| fl displays information about the DrainMode item. You can also change the default view to always display the Description column.

Now, let’s look at few examples.

Example 1: Set RDP encryption level

Step 1: View current encryption level

PS RDS:\RDSConfiguration\Connections\RDP-Tcp\SecuritySettings> dir .\EncryptionLevel | fl

Step 2: Set value of EncryptionLevel item to desired value

PS RDS:\RDSConfiguration\Connections\RDP-Tcp\SecuritySettings> Set-Item .\EncryptionLevel 2

Example 2: Specify License servers that a Remote Desktop server will use

Step 1: View the current list of License Servers in use

PS RDS:\RDSConfiguration\LicensingSettings\SpecifiedLicenseServers> dir

Step2: View the list of license servers registered with the domain controller.

PS RDS:\RDSConfiguration\LicensingSettings\RegisteredLicenseServers> dir

Step 3: add a License server to SpecifiedLicenseServers list

The simplest way to add a license server is to use new-item and specify the name of the license server that you want to add.

PS RDS:\RDSConfiguration\LicensingSettings\SpecifiedLicenseServers> New-Item -name

You can use the below command to add all license servers from the registered license server list to specified license server list.

PS RDS:\RDSConfiguration\LicensingSettings\SpecifiedLicenseServers> dir ..\RegisteredLicenseServers | new-item –force

Example 3: Join a Remote Desktop server to a Session Broker farm


PS RDS:\RDSConfiguration\ConnectionBrokerSettings> Set-Item MemberOfFarm 1 -FarmName testFarm -sessionbroker contoso-sb-test  -CurrentRedirectableAddresses


Example 4: Add a RemoteApp


PS RDS:\RemoteApps\PublishedApplications> New-Item -Name “IExplore” -ApplicationPath “c:\Program Files\Internet Explorer\iexplore.exe” -ApplicationName “Internet Explorer” -ShowInPortal 1

These are just few examples that demonstrate the various possibilities.  Almost all configuration tasks related to RD server configuration, RemoteApp, Gateway, License server, and RDV can now be performed using the RDS provider.

Also, the true potential of RDS Provider is realized when writing a script to

1.       chain multiple configuration activities together

2.       perform configuration on multiple servers

One scenario that best demonstrates the above is the creation of RD server farms. The script shown as a example at the end of this post takes a list of servers and applications as input and creates a RD server farm and creates RemoteApp on all of the servers.  Create two text files, one with a list of servers and another with a list of app paths (you can use paths with shell variables such as %windir%) and pass the names of these files as input to this script.

Since this script makes use of PowerShell remoting, before you execute the script make sure you have enabled PowerShell remoting (run Enable-PSRemoting from an elevated PowerShell Windows to enable remoting.).  

Of course this is a very rudimentary script – you can augment it easily with advanced and specific functionality to suit your needs.  Also, in our opinion, one of the important advantages of RDS provider is that one doesn’t need to be a programmer to be able write such scripts as CreateRDFarm. All one needs to know is basic PowerShellPowerShell scripting.

I hope you are as excited as we are about the possibilities that this opens up. Do let us know what you think. Also, keep watching this space for more scripts that you can put to use.


Appendix: Sample script


#Windows PowerShell script to create a RD Server farm.


if ($args[0] -eq $null -or $args[1] -eq $null -or $args[2] -eq $null ){

      Write-Host “Insuffecient parameters.`nUsage: CreateRDFarm.ps1 SessionBroker Farmname <File containing list of RDS servers> <File containing Applications to publish>”



      $sb = $args[0]

      $farmname = $args[1]



$rdsarr = get-content $args[2]

if ($rdsarr -eq $null){

      Write-Host “$args[2] cannot be read or is empty.`nUsage: CreateRDFarm.ps1 SessionBroker Farmname <File containing TS servers> <File containing Applications to publish>”




if ($args[3] -eq $null){

      Write-Host “No file containing Apps Servers specifed. TS Remote Apps will not be published.`nUsage: CreateFarm.ps1 SessionBroker Farmname <File containing TS servers> <txt file containing Applications to publish>.`n Farm creation will continue” -ForegroundColor yellow


      $apparr = get-content $args[3]

      if ($apparr -eq $null){

      Write-Host “$args[3] cannot be read or is empty.`nUsage: CreateRDFarm.ps1 SessionBroker Farmname <File containing TS servers> <File containing Applications to publish>”




# Check whether session broker service is running on the remote machine


$sbservice = Get-Service -ComputerName $sb -Name Tssdis

if( $sbservice.status -ne “Running”){

Write-host “Session Broker service is not running on $sb. Exiting farm creation”





if ($rdsarr[0] -eq $null){

      Write-Host “No TS Server specified. Atleast one TS Server need to be specified.`nUsage: CreateFarm.ps1 SessionBroker Farmname TS1 TS2 …”




#create a run space to run remote commands on the Session Broker server

$sb_remotesession = New-PSSession -ComputerName $sb


foreach ($rds in $rdsarr){


      #add ts server to Session Broker Computers group on SB server

      $tst = $rds+”$”

      invoke-command $sb_remotesession -ScriptBlock {

      net localgroup ‘Session Broker Computers’  /add $args[0] 2>$null;`

      } -ArgumentList $tst


      #join each ts server to sb farm.


            Write-Host “Joining RD server $rds to $farmname farm” -ForegroundColor magenta


            $rds_remotesession = New-PSSession -ComputerName $rds


            invoke-command $rds_remotesession -ScriptBlock { `

                  import-module RemoteDesktopServices ;`

                  $cipaddr = dir RDS:\RDSConfiguration\ConnectionBrokerSettings\RedirectableAddresses ;`

                  Set-Item RDS:\RDSConfiguration\ConnectionBrokerSettings\MemberOfFarm 1 -FarmName $args[0] -sessionbroker $args[1] -IPAddressRedirection 0 -CurrentRedirectableAddresses $cipaddr[0].Name ;`


                  -ArgumentList $farmname,$sb


      #create ts remote apps

            if ($args[3] -ne $null){


                  foreach ($app in $apparr){


                        Write-Host Publishing $app on $rds -ForegroundColor magenta


                        $ind = $app.LastIndexof(“\”)

                        $alias = $app.SubString($ind+1,$app.LastIndexOf(“.”)-$ind-1)


                        invoke-command $rds_remotesession -ScriptBlock { `

                        new-item -Path RDS:\RemoteApps\PublishedApplications -Name $args[0] -ApplicationPath $args[1]`


                        -ArgumentList $alias,$app




      #close the remote session

      Remove-PSSession $rds_remotesession



#close the sb runspace

Remove-PSSession $sb_remotesession



Shanmugam Kulandaivel
Remote Desktop Virtualization Services Team



Discussion is closed.

Feedback usabilla icon