fbpx
Use PowerShell to Automate Remote Desktop Connection Manager 2.7 Setup
By Steve Bowman
Published October 28, 2015
Estimated Reading Time: 6 minutes

An issue arises

Like many others, I use Microsoft’s Remote Desktop Connection Manager (RDC Man) daily to connect to the Servers I administer. It is a very elegant tool to use.

 

If you don’t already have it, you can download it from Microsoft at: http://www.microsoft.com/en-us/download/details.aspx?id=44989

 

Some of my favorite features include:

  • I can store credentials (with or without passwords) to make quick RDP connections
  • The desktop of each RDP session can be set to automatically resize to fit the RDC Man window.
  • It’s flexible! I can choose to view my RDP sessions inside of RDC Man (docked), or break them out across multiple monitors (un-docked).
  • I can configure servers to inherit settings from the group they are part of in RDC Man.

The list could go on and on. I love this tool! It’s great … except for one thing: it’s a pain to set up the first time, especially when you have a lot of servers to add.

 

I’ll admit the first few times I set up my connections I did it by hand. Then I realized that the connection file is just a plain text file, so I started copying and pasting. However, recently I have found myself again in a position where I need to add many connections from a new environment. I’ll admit I wasn’t looking forward to setting RDC Man up.

PowerShell to the rescue

A philosopher somewhere once said, “It is when we dread doing something that we become most inventive.” He must have been a really smart guy, because I decided then and there that I wasn’t going to hand code my RDC Man connection files anymore! I was going to automate it!

 

The resulting PowerShell script reads the site information on a Primary SCCM 2012 Site and automatically builds a RDC Man connection file, including smart groups that allow you to quickly view a list of servers by the role it is assigned.

 

Here are some screenshots of what it will look like when finished:

The list of Connection Groups. One normal group that includes all servers, and one smart group for every role present in SCCM.

The list of Connection Groups. Using PowerShell, we will create one normal group that includes all servers, and one smart group for every role present in SCCM.

 

Properties of a single server. The display name includes the site code and server name. The comment includes all the SCCM roles the server has installed.

Properties of a single server. We will use PowerShell to add the display name, using the site code and server name. The comment includes all the SCCM roles the server has installed.

 

Properties of one of the “Smart Groups”. The groupings key off the comments included for each server.

Properties of one of the “Smart Groups”. The groupings key off the comments we included using PowerShell for each server.

 

How to automate it with PowerShell

 

The script itself is rather simple, actually. I’ll walk you through how it works, then at the bottom of this post, I’ll include the entire script in case you want to try it out!

 

Note: This script must be run on the Primary Site server.

 

We start by initializing a few variables:

 

$OutputText will be used to hold the contents of the RDC Connection file that we will export at the end of the script.

 


$outputText = ""

 

 

$ServerList will be used to build a list of all site servers listed in SCCM.

 


$ServerList = ""

 

 

$ServerInfo is an array and will be used to build a custom PSObject to help build the output file.

 

 


$ServerInfo = @()

 

 

We query WMI on the SCCM Site server and get back a list of all site servers with their site code and role, which we store in $SiteServers. Replace the “xxx” with your site code.

 


$SiteServers = Get-WmiObject -Namespace root\SMS\site_xxx -Class SMS_SiteSystemSummarizer | Select-Object SiteSystem, SiteCode, Role

 

 

Due to the fact that many servers have more than one role, we put a list of unique server names into $UniqueServers.

 


$UniqueServers = $SiteServers | Select-Object @{N="SiteSystem";E={ $_.SiteSystem.toUpper()}} -Unique

 

 

Next we use a Foreach loop to pull the actual server name out of the SiteSystem field. This leaves us with a clean comma seperated list of unique server names (minus the extra text).

 


Foreach ($Server in $UniqueServers.SiteSystem) {

         $ServerName = $Server.Replace("DISPLAY=\\","")

         $ServerName = $ServerName.Replace("[""","")

         $ServerName = $ServerName.Split(".")

         $ServerName = $ServerName[0]

         $ServerList = $ServerList + $ServerName + "," 
}

We use the powershell “Split” function to turn the $ServerList variable into an array of server names.

 


$ServerList = $ServerList.Substring(0,$ServerList.Length-1)

$ServerList = $ServerList.Split(",")

This next few steps are done once for each server. We build a list of the roles that a server is assigned. Due to the fact that servers commonly contain more than one role, we are going to put this into a comma separated list also. We trim off the last comma at the end so our list is clean.

 


Foreach ($Server in $ServerList)  {
         $Name = $Server

         $Roles = @($SiteServers | Where-Object {$_.SiteSystem -like "*$Server*"} | Select $_.Roles)

         Foreach ($Role in $Roles.Role) {

                  $RoleList = $RoleList + $Role + ","

         }
        
        $Roles = $RoleList.SubString(0,$RoleList.Length-1)

 

 

We get the site code of the server that we are working on ($Server).

 


$SiteCode = $SiteServers | Where-Object {$_.SiteSystem -like "*$Server*"} | Select $_.Site -Unique

 

We create a custom object for the server we are looking at, and add the Name, Roles, and Sitecode properties. Then we reinitialize the variables to prepare to process the next server.

 


         $SiteServerOutput = New-Object -TypeName PSObject

         $SiteServerOutput | Add-Member -type NoteProperty -name ServerName -value $Name

         $SiteServerOutput | Add-Member -type NoteProperty -name Roles -value $Roles

         $SiteServerOutput | Add-Member -type NoteProperty -name SiteCode -value $Sitecode.SiteCode

         $ServerInfo += $SiteServerOutput

         $Name = ""

         $Roles = ""

         $SiteCode = ""

         $RoleList = ""

         }

 

Once we are done with the loop above, the $ServerInfo variable contains an array of custom objects, one for each server.

 

Now we start to build the output file. We create the “Header” of the RDC file using a literal string to preserve the line breaks for readability.

 

$RDCEntry = @"
<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
  <file>
    <credentialsProfiles />
    <properties>
      <expanded>True</expanded>
      <name>CM</name>
    </properties>
    <group>
      <properties>
        <expanded>False</expanded>
        <name>All Servers</name>
      </properties>
"@

 

We then loop through our custom server object to build the “static” connection node for each server.   These will be contained in the “All Servers” group.

 

   Foreach ($item in $ServerInfo) {

    $ServerName = $item.ServerName
    $Roles = $item.Roles
    $SiteCode = $item.SiteCode


    $RDCEntry += @"
        <server>
        <properties>
          <displayName>$SiteCode-$ServerName</displayName>
          <name>$ServerName</name>
          <comment>$Roles</comment>
        </properties>
        <displaySettings inherit="None">
          <thumbnailScale>1</thumbnailScale>
          <smartSizeDockedWindows>True</smartSizeDockedWindows>
          <smartSizeUndockedWindows>False</smartSizeUndockedWindows>
        </displaySettings>
      </server>
"@

  } 

  	$RDCEntry +=  "</group>" 

 

Next we build out our smart groups for each role that is present in our SCCM hierarchy. We pull this from WMI again so we have a unique list. Once again, replace the xxx with your site code.

 


$AllRoles = Get-WmiObject -Namespace root\SMS\site_xxx -Class SMS_SiteSystemSummarizer | Select-Object Role -Unique

 

 

We loop through each role and create smart group for it, based on the comments we added to the server connections above.

 

Foreach ($Role in $AllRoles)
{

$roleName = $role.Role




$RDCEntry +=  @"

    <smartGroup>
      <properties>
        <expanded>False</expanded>
        <name>$roleName</name>
      </properties>
      <ruleGroup operator="All">
        <rule>
          <property>Comment</property>
          <operator>Matches</operator>
          <value>$roleName</value>
        </rule>
      </ruleGroup>
    </smartGroup>
"@


} 


 

We write the footer of the RDC file to close it out gracefully.

 


$RDCEntry += @"
  </file>
  <connected />
  <favorites />
  <recentlyUsed />
</RDCMan>
"@ 

 

Finally, we place the RDG file on the desktop of the current user and display a message that we are done.

 

$RDCEntry | Out-File -FilePath $Env:UserProfile\Desktop\CM.Rdg -Force

$RDCEntry = ""

Write-Host "New CM.Rdg written to $Env:UserProfile\Desktop!"

 

 

Putting it all together

Now, as promised, here is the entire script.



$SiteServers = Get-WmiObject -Namespace root\SMS\site_xxx -Class SMS_SiteSystemSummarizer | Select-Object SiteSystem, SiteCode, Role
$outputText = ""
$ServerList = ""
$UniqueServers = $SiteServers | Select-Object @{N="SiteSystem";E={ $_.SiteSystem.toUpper()}}  -Unique
    $ServerInfo = @()
  
Foreach ($Server in $UniqueServers.SiteSystem) {
    $ServerName = $Server.Replace("DISPLAY=\\","")
    $ServerName = $ServerName.Replace("[""","")
    $ServerName = $ServerName.Split(".")
    $ServerName = $ServerName[0]
    $ServerList = $ServerList + $ServerName + ","
}
  $ServerList = $ServerList.Substring(0,$ServerList.Length-1)
  $ServerList = $ServerList.Split(",")
  Foreach ($Server in $ServerList)
  {
    $Name = $Server
    $Roles = @($SiteServers | Where-Object {$_.SiteSystem -like "*$Server*"} | Select $_.Roles)
    Foreach ($Role in $Roles.Role) {
    $RoleList = $RoleList + $Role + ","
    }

    $Roles = $RoleList.SubString(0,$RoleList.Length-1)
    
    $SiteCode = $SiteServers | Where-Object {$_.SiteSystem -like "*$Server*"} | Select $_.Site -Unique
    $SiteServerOutput = New-Object -TypeName PSObject
    $SiteServerOutput | Add-Member -type NoteProperty -name ServerName -value $Name
    $SiteServerOutput | Add-Member -type NoteProperty -name Roles -value $Roles
    $SiteServerOutput | Add-Member -type NoteProperty -name SiteCode -value $Sitecode.SiteCode
    $ServerInfo += $SiteServerOutput
    $Name = ""
    $Roles = ""
    $SiteCode = ""
    $RoleList = ""
  }

    $RDCEntry = @"
<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
  <file>
    <credentialsProfiles />
    <properties>
      <expanded>True</expanded>
      <name>CM</name>
    </properties>
    <group>
      <properties>
        <expanded>False</expanded>
        <name>All Servers</name>
      </properties>
"@

  Foreach ($item in $ServerInfo) {
    $ServerName = $item.ServerName
    $Roles = $item.Roles
    $SiteCode = $item.SiteCode

    $RDCEntry += @"
        <server>
        <properties>
          <displayName>$SiteCode-$ServerName</displayName>
          <name>$ServerName</name>
          <comment>$Roles</comment>
        </properties>
        <displaySettings inherit="None">
          <thumbnailScale>1</thumbnailScale>
          <smartSizeDockedWindows>True</smartSizeDockedWindows>
          <smartSizeUndockedWindows>False</smartSizeUndockedWindows>
        </displaySettings>
      </server>
"@

  }
  $RDCEntry +=  "</group>"
$AllRoles =  Get-WmiObject -Namespace root\SMS\site_xxx -Class SMS_SiteSystemSummarizer | Select-Object  Role -Unique

Foreach ($Role in $AllRoles)
{
$roleName = $role.Role

$RDCEntry +=  @"

    <smartGroup>
      <properties>
        <expanded>False</expanded>
        <name>$roleName</name>
      </properties>
      <ruleGroup operator="All">
        <rule>
          <property>Comment</property>
          <operator>Matches</operator>
          <value>$roleName</value>
        </rule>
      </ruleGroup>
    </smartGroup>
"@

}

$RDCEntry += @"
  </file>
  <connected />
  <favorites />
  <recentlyUsed />
</RDCMan>
"@

$RDCEntry | Out-File -FilePath $Env:UserProfile\Desktop\CM.Rdg -Force
$RDCEntry = ""
Write-Host "New CM.Rdg written to $Env:UserProfile\Desktop!"


Article By Steve Bowman
Steve Bowman is a Partner at Model Technology as well as their Vice President of Sales and Marketing. Steve is a father, husband, Franciscan, and lover of technology. He's bilingual in business and technology and have over 30 years of experience in selling enterprise technology solutions in a variety of industries.

Related Posts