Archives for the Month of June, 2006

Current Working Directory with PowerShell and .Net Calls

A question that occasionally comes up is, “Why doesn’t PowerShell change the [Environment]::CurrentDirectory while I navigate around the shell?”  This is always in the context of using a relative file path while working with the .Net framework.

One of the difficult aspects of this comes from the fact that PowerShell supports multiple pipelines of execution.  Although it’s not directly exposed yet, users will soon be able to suspend jobs to the background, and other concurrent tasks.

The current directory affects the entire process, so if we change the directory as you navigate around the shell, you risk corrupting the environment of jobs you have running in the background.

When you use filenames in .Net methods, the best practice is to use fully-qualified path names.  The Resolve-Path cmdlet makes this easy:

[C:\temp]
PS:37 > $reader = new-object System.Xml.XmlTextReader baseline.xml

[C:\temp]
PS:38 > $reader.BaseURI
file:///C:/Documents and Settings/<user>/baseline.xml

[C:\temp]
PS:37 > $reader = new-object System.Xml.XmlTextReader (resolve-path baseline.xml)

[C:\temp]
PS:38 > $reader.BaseURI
file:///C:/temp/baseline.xml

 

Precision Computing Turns One

It was a year ago now that Precision Computing, in its current form, opened its doors.  I’ve been writing something blog-like for longer, but it previously involved updating the HTML by hand 🙂

It’s been an interesting year – one in which we’ve seen the PowerShell community blossom from a group of passionate BetaPlace users, to a much larger and more diverse community.  We’ve played with a handful of new releases, experienced a long-awaited name change,  and perhaps most importantly – learned about PowerShell’s official release plans.

At Microsoft, we have a tradition for celebrating times like this.  When their anniversary rolls around, many people place chocolate on a chair outside of their office – usually 1 lb. for every year they’ve been at Microsoft.  It’s a great tradition – the people you work with get to indulge a little, and everybody enjoys the water cooler type of conversation that tends  to happen.

I obviously can’t distribute chocolate on the internet, but I’ve been thinking for a while about how to recreate the essence of the Microsoft chocolate tradition.  Here’s the idea:

If you own a blog, add a comment with a link to what you consider your "best" post in the last year or so.  If you don’t own a blog, add a comment with a link to a blog post that you consider to be very insightful or interesting.  Then, click around and enjoy the water cooler conversation!

Now, on for another year!

Caffe Artigiano in Vancouver

On a recent trip to Vancouver, I accidentally stumbled into a cafe called Caffe Artigiano right downtown (on Hornsby street,) and was extremely impressed.  The walls are decorated with pictures of gorgeous Latte art, and the drinks are stellar.  It turns out that the place is the home of the Canadian Barista Champion for three years running!

And with drinks like this?  It makes me want to go back to working for a coffee shop 🙂

 


Picture taken from their blog @ http://www.dwelltime.net/, although mine looked similar!

SecureStrings in PowerShell

When you use any string in the CLR, it retains that string so that it can efficiently reuse it later.  Unlike most.Net data, unused strings persist even through garbage collection cycles.  While this data is in memory, there is always the chance that it could get captured in a crash dump, or swapped to disk in a paging operation. Because some data (such as passwords, and other confidential information) may be sensitive, the .Net framework includes the SecureString class – a container for text data that the CLR stores in memory in an encrypted form.  Code that needs to interact with the plain text data inside of a SecureString does so as securely as possible.

When a cmdlet author asks you for sensitive data (i.e.: a password,) the best practice is to designate that password parameter as a SecureString in order to help keep your password confidential.   You can supply the parameter with a SecureString variable as input, or the host prompts you for the SecureString if you do not provide one.  We also have two cmdlets (ConvertTo-SecureString and ConvertFrom-SecureString) that allow you to round-trip this data to disk in a secure fashion.

By default, the SecureString cmlets use Windows’ Data Protection API when they convert your SecureString to and from a plain text representation.  The encryption key is based on your Windows logon credentials, so only you can decrypt the data that you’ve encrypted.  If you want the exported data to work on another system or separate user account, you can use the parameter sets that let you provide an explicit key.  PowerShell treats the data as an opaque blob – and so should you.

However, there are many instances when you may want to automatically provide the SecureString input to a cmdlet, rather than have the host prompt you for it.  In these situations, the ideal solution is to import a previously exported SecureString from disk (using ConvertTo-SecureString.)  This retains the confidentiality of your data, and still allows you to automate the input. 

If the data is highly dynamic (ie: coming from a CSV,) then the best approach is

$secureString = ConvertTo-SecureString "Kinda Secret" -AsPlainText –Force

The Cmdlet requires the Force parameter to ensure you acknowledge the fact that PowerShell cannot protect plain text data – even after you’ve put it in a SecureString.

The new –AsPlainText parameter set doesn’t exist in RC1, so the equivalent function is:

function New-SecureString([string] $plainText)
{
   $secureString = new-object System.Security.SecureString

   foreach($char in $plainText.ToCharArray())
   {
      $secureString.AppendChar($char)
   }

   $secureString
}

[Edit: Fixed typo]