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. However, it you can strictly type objects if you need to and 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.

PowerShell Cast Introduction

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. 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, 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.

PowerShell cast to XML

Casting to Datetime

Along the similar vein of XML, we can also cast strings to datetime objects. 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.

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!