Welcome to MSDN Blogs Sign in | Join | Help

RDP File Generation/Use of HERE-Strings

Over on the Everyday Nerd blog, I found a great blog entry you should read:  Create multiple RDP files with PowerShell.  He describes his environment where he has to manage a large set of servers using Remote Desktop (RDP).  Having to configure the RDP settings each time he connects to the server, he decided to automate the process by writing a script which generates the RDP files for him. 

The script itself is cool but the think I wanted to highlight was that the script is a great illustration of a very powerful scripting design pattern.  It uses:

  1. A Template file which defines the structure of the output
  2. A Script which takes input, applies it to the template and generates output
  3. A CSV file which drives the script

This pattern has a number of advantages including:

  • You can change the template file without touching the code. 
    • If the script is digitally signed, you can change the template without affecting the digital signature. 
    • The person updating the template might not have any programming skills
  • Using a CSV file allows you to have this script driven using the IT Pro's favorite input editor:  EXCEL.

I have a couple of suggestions for how to improve the script.

Use HERE-strings

I continue to see scripts which use lots of string processing which look difficult to create and maintain and are fragile because they are complex.  Here is the example from the script:

    # Begin building RDP file
    $temp = "`nfull address:s:" + $Entry.IP
 
    switch ($resolution) {
     
      "1024x768" {
        $temp = $temp + "`nscreen mode id:i:1"
        $temp = $temp + "`ndesktopwidth:i:1024"
        $temp = $temp + "`ndesktopheight:i:768"
  $temp = $temp + "`nusername:s:" + $Entry.USER
      }

      "1152x864" {
        $temp = $temp + "`nscreen mode id:i:1"
        $temp = $temp + "`ndesktopwidth:i:1152"
        $temp = $temp + "`ndesktopheight:i:864"
  $temp = $temp + "`nusername:s:" + $Entry.USER
      }
    }

This is exactly the sort of code we hoped to eliminate by providing HERE-strings.  HERE-Strings allow you to easily create multi-line strings (with or without variable expansion and command substitution).  HERE-Strings are NOT an advanced topic - every PowerShell scripter should take the time to learn how to use HERE-Strings.  Advanced scripters should use them because they are incredibly powerful.  Beginner scripters should use them because they are incredibly easy and reduce the complexity and fragility of your scripts.

Here is the same logic refactored and written with HERE-Strings:

    # Begin building RDP file
    $temp = "`nfull address:s:" + $Entry.IP
 
    switch ($resolution) {
     
      "1024x768" {
        $width = 1024
        $height = 768
      }

      "1152x864" {
        $width = 1152
        $height = 864
      }
    }
    $temp = $temp + @"
screen mode id:i:1
desktopwidth:i:$width
desktopheight:i:$height
username:s: $($Entry.USER)
"@

In this example I used double quotes which allow variable expansion (Notice the use of $width and $Height) and command substitution (notice the use of $($Entry.USER) [you could put any command or command sequence within $() and we'll run it and substitute it's output into the string]).

Use Verb-Noun naming and Proper Verbs

CreateRDP should be New-RDP or New-RDPFile.  What we are trying to do is to achieve a world where people will be able to guess and type and have it be right.  At the beginning, those patterns are not yet established so it might seem like "create" is the same as "new".  The problem is that if we aren't hardcore on this then 50 verbs will become 500 which will become 5,000 and we'll have an incoherent world where your guesses are useless and have ourselves to blame. I know what is going on here because it happens with me all the time - you are so focused on solving the problem, you don't want to spend the energy on getting the naming right.  At some point, that pattern will be well established and you won't have to think about it - you'll need a new name and you'll naturally pick the right ones.  Until then, you need to adopt a practice of reviewing and fixing the naming any script that you share with others.  When you share a script, you'll either be enforcing or destroying the pattern for people.  Be a force of good.

The community is the ultimate controller of whether this pattern will emerge or we'll have chaos.  I'll do whatever I can do to ensure that the artifacts that we produce enforce the pattern but the bulk of scripts are going to come from the community.  The community needs to politely self police itself.  When you see someone share a script that doesn't follow the correct naming, you need to leave a comment pointing it out and ask that the post be corrected. 

Let's be clear, that includes US.  If (when) you see use posting scripts that don't follow the pattern, call us on it and we'll get it fixed.

 

Use Pipelining Features (when available in PS V2)

One of the problems with the script is that it is hardwired to a CSV file.  It would be more flexible to declare your data requirements and then be flexible with how those data requirements are satisfied.  We are redoing the interfaces to this for the next version of the CTP so I want go into detail here but I didn't want to let the point pass either.  What you'll be able to do is to specify the parameters and then specify that their values can be retrieved from the properties of a pipelined object.  What that means is that users can create any object they want as long as it has the right property names and then pipeline that object to your command.  This is a TON more powerful/flexible then hardwiring to CSV files.  What this means is you'd be able to do things like:

PS> Import-CSV RDPLIST.CSV | New-RDPFile
PS> Invoke-Database -Query <something> | New-RDPFile
PS> Invoke-WebServer -Parameter <something> | New-RDPFile
etc

 

Enjoy!

Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Published Sunday, September 14, 2008 4:04 PM by PowerShellTeam

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: RDP File Generation/Use of HERE-Strings

Hey - Glad you liked the script!  I was like a giddy school girl when I did this!  Pretty cool stuff! :)  Cheers~

Sunday, September 14, 2008 12:31 PM by EverydayNerd

# re: RDP File Generation/Use of HERE-Strings

@Nerd

Yeah - that was very cool.  Great thinking.

jps

Sunday, September 14, 2008 1:31 PM by PowerShellTeam

# Splitting HERE-Strings

Is it appropriate to use HERE strings to setup a list of computers internal to the script.

The problem was when I split the string on newline into an array of strings there was an extra character at the end of each string in the array and I couldn't figure out why.

I ended up moving the list into an external text file that I read in during processing, which may be better overall.

My question now is why didn't the split work correctly, should I have split on a different character?

Sunday, September 14, 2008 1:59 PM by Paul Chavez

# re: RDP File Generation/Use of HERE-Strings

> My question now is why didn't the split work correctly, should I have split on a different character?

Post the code and I'll take a look.

jps

Sunday, September 14, 2008 3:06 PM by PowerShellTeam

# re: RDP File Generation/Use of HERE-Strings

It occurs in this snippet. The original case was taking a list of urls and building a query statement for logparser.

It outputs to the console as expected. It's only when examining the variable in the PowershellPlus debugger that I "see" the extra character at the end of the $item variable.

Even though it looks ok on the screen when passed into the logparser com object it failed. I think if I just used the resulting query string as a parameter to logparser.exe it worked.

$list = @"

First

Second

Third

"@

$items = $list.Split("`n")

$newstring = "SELECT "

foreach ($item in $items)

{

$newstring += "$item, "

}

$newstring

Sunday, September 14, 2008 3:38 PM by Paul Chavez

# re: RDP File Generation/Use of HERE-Strings

This probably misses the point but he could possibly use the free and great Royal TS http://code4ward.net/CS2/Default.aspx. It's a lifesaver when it comes to managing large amount of servers over RDP. I for one can't live without it anymore.

Sunday, September 14, 2008 5:01 PM by Joakim E

# re: RDP File Generation/Use of HERE-Strings

The only time I seen someone use a here-string was in Ed Wilson's Microsoft Powershell book. He uses it a lot for Help functions that display syntax .

P.S I'm not trying to see the book but it is very good !

Good Blog!

Sunday, September 14, 2008 8:09 PM by Chris Federico

# re: RDP File Generation/Use of HERE-Strings

Having been forced to do a decent amount of work in php I was familiar with the here-strings but not a fan. The additional power in posh sold me on the concept. I (now) love here-strings for generating things like email alerts; and shudder to think what life would be like without them. ;)

on a completely unrelated note, stackoverflow (a joelonsoftware/codinghorror collaboration) is open to the public, already some decent (and some not so) powershell questions and answers

http://stackoverflow.com/questions/tagged/powershell

Monday, September 15, 2008 10:34 PM by bob developer

# re: RDP File Generation/Use of HERE-Strings

Great post i will tryout the here-string. I completely agree with your comments on the naming conventions. that will make life alot easier.

Tuesday, September 16, 2008 8:24 AM by Trac3r726

# re: RDP File Generation/Use of HERE-Strings

Disregard my post about the "mystery" character.

Further investigation shows it is a problem with the Powershell Plus editor.

Tuesday, September 16, 2008 6:26 PM by Paul Chavez

# Adam Weigert Puts NetApp On a String

Adam Weigert has started a new Codeplex project PowerShell OnTap .&#160;&#160; (That brings the total

Sunday, September 21, 2008 12:23 PM by PowerShell Team Blog

# Adam Weigert Puts NetApp On a String

Adam Weigert has started a new Codeplex project PowerShell OnTap . (That brings the total number of PowerShell-related

Sunday, September 21, 2008 12:24 PM by PowerShell Team Blog

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker