Friday, June 6, 2008

Object Types & Shortcuts with PSCX

When using Powershell you'll hear over and over again about how it's all about "Objects". This can not be more true. So whats the big deal about Objects? So it's an object, big deal! Well with a language like Powershell objects are everything!! Unlike other languages, Powershell lacks any built-in functions that work strings, dates, integers, or any other object type. So you have to depend on the "Object Type" to get to that functionality, because it's the "type of object" that will provide you with the methods you need. For example.

In VBScript if you needed to convert a string to all uppercase characters you would use the built-in function "Ucase"

strMyString = "hello world"
WScript.Echo ucase(strMyString)
' This will echo back "HELLO WORLD"

Like I mentioned earlier Powershell lacks any language functions because its the "Objects" that contain the methods you'll need. So to do the same in Powershell it would be something like this.

$strMyString = "Hello World"
$strMyString.toupper()
# This returns "HELLO WORLD"

You can see that the uppercase functionality/method is built into the object itself. You didn't need to remember the name of any function, it was already there.

Now lets change the object to something else and see what happens. Lets cast this to an Character array object.

$strMyString = [char[]]$strMyString
$strMyString.toupper()

Method invocation failed because [System.Char[]] doesn't contain a method named 'toupper'.
At line:1 char:19
+ $arrString.toupper( <<<< )

Doh! What happened here?? The object is no longer of the "String object Type" its now a Character array or just an array. So now we no longer have access to all the string methods. We only have access to the "Array" methods. You'll know this by typing.

$strMyString.gettype()

So now that you know that the Type of object is so important. How do you know for sure what type of object your dealing with without typing gettype() for each object you want to know about? This is where some of the PowerShell Community Extensions (PSCX) handy functions and scripts come into play. You can find the PSCX tools here.

Once installed you can now type Get-TypeName, which is a script, and the name of the variable and get the following output.

Get-TypeName $strMyString
Char[]

You can also use it in the pipeline and it will get the object type of every array item.

$strMyString | Get-TypeName
Char
Char
Char
Char
Char
Char
Char
Char
Char
Char
Char

Or

$numbers = "one", 2, "three", 4, "five"
$numbers | Get-TypeName.ps1
String
Int32
String
Int32
String

There is also another really handy function called "Get-PropertyValue"
You use this in the pipeline when filtering so you dont lose the object type like you would if you filtered using the Select-object cmdlet.

$el = Get-EventLog -LogName application -Newest 1 | Get-PropertyValue message
$el
The VSS service is shutting down due to idle timeout.

$el | Get-TypeName.ps1
String
$el = Get-EventLog -LogName application -Newest 1 | Select-Object message
$el | Get-TypeName.ps1
PSCustomObject


You can see that using Select-object you lose the type of object (Select-Object will wrap your object inside a PS Custom object and you'll lose your native object type) and in result lose all of the "String Type" methods versus using PSCX's function Get-PropertyValue the object type is retained. So like before you can do this.

$el.toupper()

No comments: