Importing Windows Azure Cloud Services into Remote Desktop Connection Manager (RDC Man)

This is the third article in what has somehow turned into a mini-series. Previous posts are:

The first post showed how to manually add Azure VMs into RDC Man, and the second post gave a PowerShell script that automated the process.

Since then, RDC Man 2.7 has been released with a raft of updates and new features, but one in particular that I’ve been waiting for: load balancer config. This setting allows you to connect to specific role instances in Web and Worker Roles when working with Cloud Services leveraging Platform-as-a-Service (PaaS) in Azure.

If you just want to get the script and create your RDC Man configuration then skip ahead to the Getting Started section..

Tidying Up

As I revisited the PowerShell script from the previous post to add support for PaaS it got fairly complicated quite quickly. It was a script that I put together quite quickly and there were a couple of things that made it hard to extend. The first was that the process for getting the data was tightly coupled with the process for updating the output file. The second was that the code had pipelines with if statements dotted throughout.

Having been through the process of updating the script, the result feels like a more PowerShell way of doing things. The core part of the script is shown below:

Get-AzureService | %{
    $service = $_
    $serviceName = $service.ServiceName

    Get-AzureVM -ServiceName $serviceName -ErrorAction Ignore | %{
        $vm = $_
        $rdpEndpoints = @($vm.VM.ConfigurationSets.InputEndpoints | ?{$_.LocalPort -eq 3389})
        if($rdpEndpoints.Length -gt 0){
            New-Object PSObject -Property @{
                ServiceName = $serviceName
                Name = $vm.DNSName
                DisplayName = $vm.Name
                Port = $rdpEndpoints[0].Port

    $production = @(Get-AzureDeployment -ServiceName $serviceName -Slot Production -ErrorAction SilentlyContinue)
    $staging = @(Get-AzureDeployment -ServiceName $serviceName -Slot Staging -ErrorAction SilentlyContinue)
    $combined = $production + $staging
    $combined | %{
        $deployment = $_
        $deployment.RoleInstanceList | ?{
                ($_.InstanceEndpoints | ?{$_.Port -eq 3389}).Count -gt 0
            } | %{
            $roleInstance = $_
            New-Object PSObject -Property @{
                ServiceName = $serviceName
                Name = $deployment.Url.ToString()
                RoleName = $roleInstance.RoleName
                Slot = $deployment.Slot
                DisplayName = $roleInstance.InstanceName
                Port = 3389
                LoadBalanceInfo = "Cookie: mstshash=" + $roleInstance.RoleName + "#" + $roleInstance.InstanceName
} | addServer # add to the tree

The starting point for the script is to get all of the cloud services using Get-AzureService (this includes PaaS and IaaS). From there, the services are piped into a block that looks for VMs (i.e. IaaS) that are in the service and Role Instances (i.e. PaaS).

On the IaaS side, we use Get-AzureVM. The outputs of this are passed through a foreach (using the ‘%’ syntax) which checks if the VM has endpoints configured to listen on the RDP port (3389). If so then we create a new object that describes the relevant information. Since that new object isn’t captured it is passed to the outer pipeline.

In the same pipeline handling for the service objects we also call Get-AzureDeployment to get PaaS instances. Since there can be Production and Staging slots for this we call the cmdlet twice and combine the results before passing this through another pipeline. This pipeline then processes deployments and filters out any that haven’t got endpoints configured to listen on the RDP port, and then creates a new object hold the necessary information for PaaS instances. Again, this object isn’t captured so flows into the outer pipeline along with the IaaS information.

The outer pipeline is passed to addServer which adds each item into the XML file ready to be saved.

There are still things I don’t massively like about the script – partly that it’s a script and I wonder if it would be better as a module that exports a cmdlet. Also, it doesn’t let you specify the filename to save as, etc. All things that would be nice, but it’s getting late Winking smile 

Getting Started

First things first, get RDC Man 2.7!

Next, get the Azure Powershell cmdlets and configure them for your subscription (see my previous post for instructions)

Finally, grab the updated script and run it from the PowerShell environment where you’ve set up your subscription. This will created the AzureVMs.rdg file that you can load in RDC Man.

Don’t forget that the configuration in RDC Man is hierarchical, so you can set the password at the role level for a PaaS role and all instances will inherit that password Smile