RDP File Generation/Use of HERE-Strings

RDP File Generation/Use of HERE-Strings

  • Comments 12

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

Leave a Comment
  • Please add 1 and 8 and type the answer here:
  • Post
  • Hey - Glad you liked the script!  I was like a giddy school girl when I did this!  Pretty cool stuff! :)  Cheers~

  • @Nerd

    Yeah - that was very cool.  Great thinking.

    jps

  • 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?

  • > 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

  • 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

  • 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.

  • 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!

  • 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

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

  • Disregard my post about the "mystery" character.

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

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

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

Page 1 of 1 (12 items)