When you store data in a variable, PowerShell can store it how you want it to be if you use the correct data type. This blog post will show you how that works and which data types I mostly use for my scripts.
What are data or reference types?
There are two ways in which you can find the types being referenced: data or reference. The Microsoft Learn documents refer to it like this:
“In PowerShell, each value has a type, and types fall into one of two main categories: value types and reference types. Consider the type int
, which is typical of value types. A value of type int
is completely self-contained; all the bits needed to represent that value are stored in that value, and every bit pattern in that value represents a valid value for its type. Now, consider the array type int[]
, which is typical of reference types. A so-called value of an array type can hold either a reference to an object that actually contains the array elements, or the null reference whose value is $null
“
Source: https://learn.microsoft.com/en-us/powershell/scripting/lang-spec/chapter-04?view=powershell-7.4
Other articles refer to it as data types, for example, this article from ScriptRunner: https://support.scriptrunner.com/articles/#!coding/powershell-data-types
But what can you do with it?
In PowerShell, you can store data in a Variable. Depending on what you try to store, it might not be in the correct format for further use in your script. In the chapters below, I will show you the types that I usually use to get things done 😉
[array]
This will create an array (Collection) of items you can use individually. When filling a variable, it will change to the System.Array BaseType for many things, but not always. You can specify [array] in front of the variable, for example: (Get-ChildItem will return an array by default, just an example 🙂 )
[array]$array=Get-ChildItem
[datetime]
By using [datetime], you will have the option to use the different methods for calculation or formatting. For example:
PS C:\Users\HarmVeenstra> $datetime=get-date PS C:\Users\HarmVeenstra> $datetime.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True DateTime System.ValueType
Because it’s in this format, you can use things like:
PS C:\Users\HarmVeenstra> $datetime.DayOfWeek Thursday PS C:\Users\HarmVeenstra> $datetime.Hour 14 PS C:\Users\HarmVeenstra> $datetime.AddHours(-1) donderdag 11 april 2024 13:59:08
[string]
The simplest one is just a simple line of text without any carriage return. For example:
C:\Users\HarmVeenstra> $string="This is just a simple line of text" C:\Users\HarmVeenstra> $string This is just a simple line of text C:\Users\HarmVeenstra> $string.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object
Using “.GetType()” behind the variable will show that the BaseType is System.Object with a String type.
[version]
This is something that I use to compare versions of applications or PowerShell modules. For example:
PS C:\Users\HarmVeenstra> $version='2.3.2' PS C:\Users\HarmVeenstra> $version.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object PS C:\Users\HarmVeenstra> $version 2.3.2
The $version is just a string now, but if you use [version]… It will format it in Major, Minor, Build, and Revision, which is better for comparing versions:
PS C:\Users\HarmVeenstra> [version]$version='2.3.2' PS C:\Users\HarmVeenstra> $version.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Version System.Object PS C:\Users\HarmVeenstra> $version Major Minor Build Revision ----- ----- ----- -------- 2 3 2 -1
[xml]
When working with XML files, you can use [xml] to store output straight away in XML format. For example: (Example.xml is an Office XML config for installation)
PS C:\Users\HarmVeenstra> $xml=Get-Content C:\temp\example.xml PS C:\Users\HarmVeenstra> $xml <Configuration ID="1ea22db9-fbc6-4254-aea8-7c5fa6b96b07"> <Add OfficeClientEdition="64" Channel="MonthlyEnterprise" SourcePath="\\test.local\data\software\microsoft\m365" AllowCdnFallback="TRUE"> <Product ID="O365ProPlusRetail"> <Language ID="MatchOS" /> <Language ID="zh-cn" /> <Language ID="hr-hr" /> .....
If you use [xml], then it knows it’s an XML file and will look like this:
PS C:\Users\HarmVeenstra> [xml]$xml=Get-Content C:\temp\example.xml PS C:\Users\HarmVeenstra> $xml.getType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False XmlDocument System.Xml.XmlNode PS C:\Users\HarmVeenstra> $xml Configuration ------------- Configuration PS C:\Users\HarmVeenstra> $xml.Configuration ID : 1ea22db9-fbc6-4254-aea8-7c5fa6b96b07 Add : Add Property : {SharedComputerLicensing, PinIconsToTaskbar, SCLCacheOverride, AUTOACTIVATE…} Updates : Updates RemoveMSI : RemoveMSI AppSettings : AppSettings Display : Display Logging : Logging PS C:\Users\HarmVeenstra> $xml.Configuration.RemoveMSI.IgnoreProduct ID -- InfoPath InfoPathR PrjPro PrjStd SharePointDesigner VisPro VisStd PS C:\Users\HarmVeenstra>
Wrapping up
I use these data types/references in my script to ensure a variable is in the correct format. You can use others if you follow the links mentioned above in the first chapter.
If you’re adding a lot of elements to an array, e.g. in a loop, it can get very slow because every item you add creates a new copy of the array that’s one element larger. There is a .net type similar to Arrays that’s much faster for that use case.
Instead of
$mySlowArray = @()
use
$myFastArray = [System.Collections.ArrayList] @()
The difference is huge.
I’m not into .NET enough, but will try that! (Not a programmer background)