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