PowerShell is not a strictly-typed language meaning it doesn’t force you to define specific types of objects every time you need to create one. You can use PowerShell to convert strings to ints, a string to dates, and any other similar type. You can cast objects from one type to another.
Everything is an object in PowerShell. But, you don’t have to specifically tell PowerShell what kind of object you want.
For example, query a service with the Get-Service
command check to see what kind of object it returns with the Get-Member
command. Notice the TypeName
that Get-Member
returns is of type System.ServiceProcess.ServiceController.
PS> Get-Service -Name wuauserv | Get-Member
TypeName: System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
<SNIP>
You didn’t have to explicitly tell PowerShell you’d like that type of object, it just did it.
However, what if you don’t want that kind of object? Perhaps you need to call some specific method on a particular type of object or need to reference a different object’s properties. In that case, you’ll use PowerShell to cast that object to another or perform a type conversion.
Converting a String to an Int
Casting is a programming term that defines “converting” one like object type to another. Not all objects can be cast to one another though.
Let’s say you’ve got a string defined as a number. You define a string by enclosing it in single or double quotes like below.
PS> $string = '1'
PS> $string.GetType().Name
String
When you check out the value of $string
, you’ll notice that it’s 1. Simple enough.
PS> $string
1
If $string
is the number 1, you should be able to add a number to that, correct? Let’s find out.
PS> $string + 2
12
Umm..last time I checked 1 + 2 wasn’t 12. What’s going on?
Since $string
is just string data, PowerShell didn’t add the two numbers together. Instead, it concatenated them together essentially just merging the two.
To get PowerShell to add the two numbers, we must first tell PowerShell that $string
is actually a number by converting the string to an int. To do that, we use PowerShell to explicitly cast that string to an integer type using a cast operator.
PS> $string = [int]$string
1
Let’s now try to add the two numbers together again.
PS> $string + 2
3
Since we cast $string
to an integer or use PowerShell to “convert” the string to an int, PowerShell now has the ability to add them together. Casting objects changes their properties entirely allowing you to perform different actions on them.
Other Useful Casting Scenarios
In PowerShell, you can cast all kinds of objects.
Casting to XML
For example, take an XML file. An XML file is simply a bunch of strings. PowerShell has no idea XML is a structured format.
For example, perhaps we have a simple XML file that looks like the following:
<person>
<firstname>Adam</firstname>
<lastname>Bertram</lastname>
<levelofawesome>Really high</levelofawesome>
</person>
If this were in a file at C:\person.xml, you’d read it with the Get-Content
command and it would return the XML or what PowerShell thinks is a bunch of strings.
PS C:\> Get-Content C:\person.xml
<person>
<firstname>Adam</firstname>
<lastname>Bertram</lastname>
<levelofawesome>Really high</levelofawesome>
</person>
However, you know that this is XML, not just a bunch of strings and you need to perform some XML searches using XPath on it. PowerShell has a concept called type accelerators which allows you to easily cast this group of strings that look like XML to an actual XML object.
Prefacing the variable declaration with [xml]
tells PowerShell to cast the group of strings it’s getting from Get-Content
to an data type XML object. Now you can see below you reference properties like person and all of the attributes.
PS> [xml]$person = Get-Content -Path 'C:\person.xml'
PS> [xml]$person
person
------
person
PS> ([xml]$person).person
firstname lastname levelofawesome
--------- -------- --------------
Adam Bertram Really high
You can also see now that the object is of type System.Xml.XmlDocument which uncovers a slew of XML-specific methods and properties you can use.
Converting a String to a Date
Along the similar vein of XML, we can also cast strings to datetime objects or use PowerShell to convert a string to a date. To create a datetime object, simply define a string that looks like a date such as 1/20/80. To you and me this is a date but PowerShell has no idea as you can see. There is no date-specific things to do on this. It’s just a string.
PS> $date = '1/20/80'
PS> $date | Get-Member
PS C:\> $date | Get-Member
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Clone Method System.Object Clone(), System.Object ICloneable.Clone()
CompareTo Method int CompareTo(System.Object value), int CompareTo(string strB), int IComparable.CompareTo(System.Object obj), int ...
Contains Method bool Contains(string value)
CopyTo Method void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
EndsWith Method
<SNIP>
However, prefacing that string with [datetime]
casts that string to a datetime object which then allows you to take advantage of a number of datetime-specific methods and properties.
PS> [datetime]$date = '1/20/80'
PS> $date | Get-Member
TypeName: System.DateTime
Name MemberType Definition
---- ---------- ----------
Add Method datetime Add(timespan value)
AddDays Method datetime AddDays(double value)
AddHours Method datetime AddHours(double value)
AddMilliseconds Method datetime AddMilliseconds(double value)
AddMinutes Method datetime AddMinutes(double value)
AddMonths Method datetime AddMonths(int months)
<SNIP>
Casting Hashtables to PSCustomObject
For the last example and one I commonly do is casting a hashtable to a PSCustomObject type.
PS> $person = @{'FirstName' = 'Adam'; 'LastName' = 'Bertram'}
PS> $person.GetType().Name
HashTable
PS> ([pscustomobject]$person).GetType().Name
PSCustomObject
Once the object is of PSCustomObject, you can then reference object properties like $person.FirstName
, $person.LastName
and so on.
Summary
In this blog post, you learned about how PowerShell handles object and how PowerShell casts certain objects to others. We covered some common casting like strings to integers and strings to datetime objects and also went into a PowerShell concept called type accelerators which provides a shortcut to casting objects to various .NET objects.
If you’d like to learn more about how PowerShell handles objects and even building your own custom types using the less-known PSTypeName feature, check out Building Custom Object Types with PowerShell and PSTypeName.