Contact

admin

About Me · Send mail to the author(s) E-mail · Twitter

At GROSSWEBER we practice what we preach. We offer trainings for modern software technologies like Behavior Driven Development, Clean Code and Git. Our staff is fluent in a variety of languages, including English.

Feed Icon

Tags

Open Source Projects

Archives

Blogs of friends

Now playing [?]

  1. Nolan feat. Amber Jolene – Everyday & Everynight (KANT Remix)
  2. Todd Terje – Inspector Norse
  3. Kyodai Feat. Stee Downes – Music Rises Up (Claptone Remix)
  4. Miami Horror – Ultraviolet
  5. Miami Horror – Illuminated
Audioscrobbler/Last.fm

ClustrMap

Creating Remote Desktop Connection Files On The Fly With PowerShell

Posted in .NET | PowerShell at Friday, February 13, 2009 6:28 PM W. Europe Standard Time

About a month ago I got myself an IBM Lenovo X301 laptop. It’s the third machine I regularly use: I have a desktop at work, one workstation at home and now there also is the sweet X301. Even with only the second machine at work in place I found it crucial to keep my work environments automatically in sync. Live Mesh has been of great help with that. Despite being a CPU hog at times, it’s a great tool to synchronize your files across machines.

Now with Remote Desktop Connection files (*.rdp) there is actually a bit more work involved than just syncing files. My workstations both have two monitors and I like Remote Desktop windows to be placed on the second monitor. The laptop, on the other hand just has a single display (surprise!) and less screen real estate. Because of the varying screen resolutions a RDP window on my home workstation will not fit the display area at work without obscuring other UI  elements like the taskbar. On the laptop, the situation gets worse as the display is simply not large enough to fit my default window size of 1500x1024 pixels.

Desktops

The dimensions and location of the Remote Desktop window is stored in the plain-text RDP file itself. A conceivable solution might be to create three RDP files per server, one for each of my machines. Actually this would involve touching three files every time I need to change some value for the connection. Horrible.

Fortunately there is PowerShell to the rescue. There’s even a script that you can use to create RDP files on the fly. You’ll have to patch line 178 to make it work (see below). Also make the Set-RDPSetting function global by uncommenting lines 87 and 216.

# Old
$content += @("${tempname}:$($datatypes[$tempname]):$tempvalue")

# New
$content += @("${tempname}:$($datatypes[$tempname]):$tempvalue" + [System.Environment]::NewLine)

Now that we're set to use the Set-RDPSetting function, let us create a script to create a RDP file in the system’s temporary folder. See the highlighted lines below, there are three hashtables:

  • $workstations for your workstations (mine are AXL, FIRIEL and EOWYN),
  • $servers for the RDP servers you want to connect to and
  • $defaults for default connection properties.
. c:\Path\To\Set-RDPSetting.ps1

$workstations = @{
	'AXL' = @{
		'desktopwidth' = 1500
		'desktopheight' = 1024
		}
	'FIRIEL' = @{
		'desktopwidth' = 1300
		'desktopheight' = 800
		}
	'EOWYN' = @{
		'desktopwidth' = 1300
		'desktopheight' = 800
		}
	}
	
$servers = @{
	'192.168.6.161' = @{
		'session bpp' = 24
		'domain' = 'DEVELOPMENT'
		}
	'host.with.ssl.certificate' = @{
		'session bpp' = 24
		'authentication level' = 2
		'disable wallpaper' = $true
		'desktopwidth' = 1280
		'desktopheight' = 1024
		}
	}

# http://dev.remotenetworktechnology.com/ts/rdpfile.htm
$defaults = @{
	'allow desktop composition' = $true
	'allow font smoothing' = $true
	'alternate shell' = $null
	'audiomode' = 2
	'authentication level' = $false
	'auto connect' = $true
	'autoreconnection enabled' = $true
	'bitmapcachepersistenable' = $true
	'compression' = $true
	'connect to console' = $false
	'desktopheight' = $null
	'desktopwidth' = $null
	'disable cursor setting' = $false
	'disable full window drag' = $false
	'disable menu anims' = $true
	'disable themes' = $false
	'disable wallpaper' = $false
	'displayconnectionbar' = $true
	'domain' = $null
	'drivestoredirect' = '*'
	'full address' = $args[0]
	'keyboardhook' = 1
	'maximizeshell' = $false
	'negotiate security layer' = $true
	'prompt for credentials' = $false
	'promptcredentialonce' = $true
	'redirectclipboard' = $true
	'redirectcomports' = $false
	'redirectdrives' = $false
	'redirectposdevices' = $false
	'redirectprinters' = $false
	'redirectsmartcards' = $false
	'remoteapplicationmode' = $false
	'screen mode id' = 1
	'server port' = 3389
	'session bpp' = 32
	'shell working directory' = $null
	'smart sizing' = $true
	'username' = 'agross' # Does not really matter what's in here.
	# http://blogs.msdn.com/ts/archive/2008/09/02/specifying-the-ts-client-start-location-on-the-virtual-desktop.aspx
	'winposstr' = '0,3,2046,129,3086,933'	
	}

Next we check if the local machine has a configuration section in the $workstations hashtable and the script has been called with parameters.

if ($workstations.Keys -inotcontains $Env:ComputerName)
{
	"The local computer is not configured."
	exit
}

if ($args -eq $null -or $args.Length -eq 0)
{
	"No arguments. Supply the RDP server name as the first argument."
	exit
}

Note the Patch-Defaults function and how we use it to add and replace keys in the $defaults hashtable. The replacement values come from $workstations and $servers, with the server settings having precedence. This way, you can configure the connection profile according to the current machine and the server to which the connection will be made. Flexibility!

function Patch-Defaults
{
	param(
		[Hashtable] $defaults = $(Throw "Defaults hashtable is missing"),
		[Hashtable] $patch = $(Throw "Patch hashtable is missing")
		)

	end
	{
		if ($patch -ne $null)
		{
			$patch.GetEnumerator() | ForEach-Object { $defaults[$_.Name] = $_.Value }
		}
	}
}	

Patch-Defaults -Defaults $defaults -Patch $workstations[$Env:ComputerName.ToUpper()]
Patch-Defaults -Defaults $defaults -Patch $servers[$args[0].ToLower()]
$defaults.GetEnumerator() | Sort-Object -Property Name

Now that we have all connection properties in place, we create a temporary connection file from the hashtable key/value pairs and start mstsc.exe with that file.

$tempFile = [System.IO.Path]::GetTempFileName()
$defaults.GetEnumerator() | Sort-Object -Property Name | Set-RDPSetting -Path $tempFile -Name $_ -Value $_

# For debugging purposes.
#"Temporary file: " + $tempFile
#Get-Content $tempFile
#Read-Host

$MstscCommand = $Env:SystemRoot + "\system32\mstsc.exe"
&$MstscCommand $tempFile

How do we use the script we just created?

You can either create batch files calling the script or use a tool like SlickRun to execute PowerShell with the script.

@powershell.exe -noprofile -command .\Open-CustomRDP.ps1 your.server.example

Another tedious task has been automated!

All comments require the approval of the site owner before being displayed.
(will show your gravatar icon)
 
[Captcha]Enter the code shown (prevents robots):

Live Comment Preview