Saturday, February 03, 2007

HooRah! for PowerShell CmdLets

I had to blog this.  PowerShell is so neat that it drives me into a frenzy.

I was adding the capability of taking input from a file.  I decided that any good system would be smart enough to recognize a file name in a commandline so I named the parameter  "File" and defined it as a "System.IO.FileInfo" type.

Here is what PowerShell does for us with a little help from NET classes.  Remember that I am only receiving a FileInfo type into my property.

PS> get-computer -file d:\computers.txt               
                 
Services                                   Name     IsPingable 
--------                                   ----     ---------- 
{Alerter, ALG, AppMgmt, aspnet_state...}   omega    True 
                                           test1    False 
{Alerter, ALG, AppMgmt, aspnet_state...}   test2    True 
                                                                               

As you can see above sending a file name on the commandline is automatically detected as a file and loads the FleInfo into the CmdLet.  All I have to do in code is to open the Fileinfo called _file with a _file.OpenText() into a streamreader and begin reading the lines out of the file.

This also works like the following:

PS>dir d:\computers.txt|get-computer
VERBOSE: DefaultSet                                                                                                                         
  
Services                                       Name    IsPingable 
--------                                       ----    ---------- 
{Alerter, ALG, AppMgmt, aspnet_state...}       omega   True 
                                               test1   False 
{Alerter, ALG, AppMgmt, aspnet_state...}       omega   True 
                                               test2   False 
{Alerter, ALG, AppMgmt, aspnet_state...}       omega   True 

As you can see it also takes a FileInfo from the pipeline and, with the exact same three or four lines of code, it gets the file contents and runs the CmdLet.

This is exactly the way I have always seen code as working.  In the past I always trid to design code systems that leveraged the context.  NET does this extremely well.  Declaritive systems are much easier to work with because they usually exhibit behaviors like above.  Of course it does become necessary to think around this or some very weird behaviors can result.  This is not hard with NET languages since the NET classes and the CLR have anticipated this need and provide numerous mechanism to guard against eratic code behavior starting with very good strong typing.

Just for Fun and Info - The CmdLet code

The Parameter

<Parameter( _ ParameterSetName:="FileSet", _ ValueFromPipeline:=True)> _ Public Property File() As System.IO.FileInfo Get Return _File End Get Set(ByVal value As System.IO.FileInfo) _File = value End Set End Property

The Code

 

Case Is = "FileSet" Dim f As StreamReader = _File.OpenText() Dim line As String While Not f.EndOfStream line = f.ReadLine() GetComputer(line) End While f.Close() End Select

Doesn't matter if the name of FIleInfo comes from the pipeline or the commandline.   It treats them all the same.

I can also enter the command as : "d:\computers.txt"|get-computer

The string will be recognized by PS, I believe, as a file name and avoind the need for a dir command.

The following also works:

get-computer host1

get-computer host1,host2,host3

Also

"host1","host2","host3"|get-computer

Get-Computer alone raises a prompt for the user to enter one or more names.  All of this done by adjusting the Parameter Attributes and the CmdLet Property types. ( Al little attention to PropertySets also helped)

Almost all "declaritive" with an extremely small amount of code.

No comments:

Post a Comment