Working With PowerShell Variables

This entry is part 6 of 9 in the series Learn PowerShell

So far in the Learn PowerShell series we have been running cmdlets directly. As you begin to write more advanced PowerShell, you’ll need the ability to save output to PowerShell variables. Saving data into variables expands your PowerShell capabilities, enabling you to work with outputs to generate powerful insights and capabilities.

Declaring PowerShell Variables

As discussed in previous lessons PowerShell deals with objects. PowerShell variables are just a named object that stores the object data you specify. Create named objects using the $ character followed by the variable name. A quick example demonstrates how simple this is:

Get-Process
$processes = Get-Process
$processes

Get-Process of course gets all the processes on the system as a System.Diagnostics.Process object type. In the second line, we declare the $processes variable and store the object returned from Get-Process. We can confirm this by running the third line which returns the exact same object data.

Now that we have that information stored in $processes it is no longer necessary to run Get-Process each time we want different information. Consider the following example:

#----------------------------------------
# not using variable
Get-Process | Where-Object {$_.CPU -gt 5000} #find processes keeping the CPU busy
Get-Process | Sort-Object WorkingSet64 -Descending #sort processes by memory usage
#----------------------------------------
# using variable
$processes = Get-Process
$processes | Where-Object {$_.CPU -gt 5000} #find processes keeping the CPU busy
$processes | Sort-Object WorkingSet64 -Descending #sort processes by memory usage
#----------------------------------------

In the first example notice Get-Process had to be run twice to get results. The second example is more efficient as it stores the first run in a variable. Afterwards, it can be manipulated endlessly to obtain additional information.

Video

If you prefer video format over written documentation I discuss this topic in the following TechThoughts video:

Understanding PowerShell Variables

PowerShell in not a strong typed language. This means that PowerShell variables can be declared without specifying the data type of the variable. Have a look:

$myNewVariable

You’ve just declared a new PowerShell variable, $myNewVariable. What type of variable is this? Is it a string? Is it an integer? A boolean? In PowerShell, this new variable has the potential to be anything. If you were to load it with a string, it would become a string data type. Assigning it an integer would cause it to become an integer. Loading it with Get-Process would cause it to become a System.Diagnostics.Process object type.

Variable Data types

Lets perform a few basic operations to highlight how variables can become different types of data.

#----------------------------------------
$total = 2 + 2
$total
$total | Get-Member
#----------------------------------------
$total = '2 + 2'
$total
$total | Get-Member
#----------------------------------------

If you run lines two and three in this example, you’ll find that $total contains the result of 4. Because we provided an integer based operation in line two, $total becomes an integer type. You can confirm this with Get-Member in line four.

In line six, we wrap the operation in quotes, forming a string. This changes the data type and $total is now of type string. Note that $total now instead contains the result of 2+2. This is because $total is a literal string, and no math operation was performed. You can confirm this with Get-Member in line eight.

Working with different variable types

Because PowerShell variables can be of any data type, it is important that you understand the data type of the variable you are working with. Consider the two operations below:

#----------------------------------------
$num1 = 2
$num2 = 2
$total = $num1 + $num2
$total
#----------------------------------------
$num1 = '2'
$num2 = '2'
$total = $num1 + $num2
$total
#----------------------------------------

Initially $num1 and $num2 are loaded with integer numbers. When a math operation is performed on line four, this causes $total to also become of type integer with a result of 4.

In the second example $num1 and $num2 are loaded with strings. When the same operation is performed on line 9, this causes $total to become a string as well, with a result of 22! This is why it is crucial to understand what variable type you are working with, as it can change the outcome of your results!

Strongly typing variables

One method of dealing with this is to strongly type your variables. Instead of letting PowerShell decide what data type your variable will be, you can specify it. Look a the following example:

[int]$num1 = '2'
[int]$num2 = '2'
$total = $num1 + $num2

In our previous examples when we wrapped numbers in quotes, it loaded them into literal string variables. Note in this example that the variable is front loaded with [int]. This is telling PowerShell that you want this variable to be of type int. Despite that the 2’s are wrapped in quotes, PowerShell will load them as integer numbers and $total will be 4.

Converting variable types

You can convert variables to other data types. In the example directly above $total is of type integer. There may be a need to have it converted to type string though. Try the following:

#take the $total variable from the previous example, and convert it to a string
$iAmAStringNow = $total.ToString()

In this example we declare a new variable, $iAmAStringNow and load in $total.ToString(). $total of course, is an integer, but what is the .ToString() about? This is a method that is being used to convert $total to a string. How did I know that I could use the ToString method on $total? I used Get-Member to verify what methods were available for that variable – covered in our first lesson in the series. Look at all the methods available for $total:

$total | Get-Member

   TypeName: System.Int32
Name        MemberType Definition
----        ---------- ----------
CompareTo   Method     int CompareTo(System.Object value), int CompareTo(int value), int IComparable.CompareTo(…
Equals      Method     bool Equals(System.Object obj), bool Equals(int obj), bool IEquatable[int].Equals(int ot…
GetHashCode Method     int GetHashCode()
GetType     Method     type GetType()
GetTypeCode Method     System.TypeCode GetTypeCode(), System.TypeCode IConvertible.GetTypeCode()
ToBoolean   Method     bool IConvertible.ToBoolean(System.IFormatProvider provider)
ToByte      Method     byte IConvertible.ToByte(System.IFormatProvider provider)
ToChar      Method     char IConvertible.ToChar(System.IFormatProvider provider)
ToDateTime  Method     datetime IConvertible.ToDateTime(System.IFormatProvider provider)
ToDecimal   Method     decimal IConvertible.ToDecimal(System.IFormatProvider provider)
ToDouble    Method     double IConvertible.ToDouble(System.IFormatProvider provider)
ToInt16     Method     short IConvertible.ToInt16(System.IFormatProvider provider)
ToInt32     Method     int IConvertible.ToInt32(System.IFormatProvider provider)
ToInt64     Method     long IConvertible.ToInt64(System.IFormatProvider provider)
ToSByte     Method     sbyte IConvertible.ToSByte(System.IFormatProvider provider)
ToSingle    Method     float IConvertible.ToSingle(System.IFormatProvider provider)
ToString    Method     string ToString(), string ToString(string format), string ToString(System.IFormatProvide…
ToType      Method     System.Object IConvertible.ToType(type conversionType, System.IFormatProvider provider)
ToUInt16    Method     ushort IConvertible.ToUInt16(System.IFormatProvider provider)
ToUInt32    Method     uint IConvertible.ToUInt32(System.IFormatProvider provider)
ToUInt64    Method     ulong IConvertible.ToUInt64(System.IFormatProvider provider)
TryFormat   Method     bool TryFormat(System.Span[char] destination, [ref] int charsWritten, System.ReadOnlySpa…

Working with quotes and PowerShell variables

As you’ve seen previously, quotes can greatly impact the functionality of a command. An operation will perform very differently with a string vs an integer. It is possible to escape operations using different types of quotes. Lets look at an example:

$literal = 'Two plus one equals: $(1 + 2)'
$literal
$escaped = "Two plus one equals: $(1 + 2)"
$escaped

Single quotes will always result in a literal string. This means that $literal contains exactly what was loaded into it. It is a literal string. Double quotes will still create a string, but are capable of working with dynamic components within that string. Note that by escaping the operation 1 + 2 with the syntax $(1 + 2) that we are telling PowerShell we want the variable result of one plus two. Thus, $escaped results in: Two plus one equals: 3

Write-Host '$escaped'
Write-Host "$escaped"

Again, we have an example with single (literal) vs doulbe (dynamic) quotes. Remember, both of these still result in a string, but note the differences by trying these out in your own console!

Reserved (Constant) PowerShell variables

There are few PowerShell variable names that are constant and therefore reserved. This means you won’t be able to use these variable names. You can familiarize yourself with this short list by running:

# Get a list of variable names in use
Get-Variable

Attempts to load into a constant variable will result in an error similar to the one below:

$HOME = 'c:\test'
Cannot overwrite variable HOME because it is read-only or constant.
At line:1 char:1
+ $HOME = 'c:\test'
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo          : WriteError: (HOME:String) [], SessionStateUnauthorizedAccessException
+ FullyQualifiedErrorId : VariableNotWritable

PowerShell Environmental variables

In addition to a few constant variables, PowerShell has variables reserved for some environment data. You can see a list of these with the following command:

# Get a list of environment variables
Get-ChildItem env:

These contain information about the environment PowerShell is running in. Examples include computer name ( $env:COMPUTERNAME ), and the current user you are running as ( $env:USERNAME ).

Putting it all together with an example

$path = Read-Host -Prompt 'Please enter the file path you wish to scan for large files...'
$rawFileData = Get-ChildItem -Path $path -Recurse
$largeFiles = $rawFileData | Where-Object {$_.Length -gt 100MB}
$largeFilesCount = $largeFiles | Measure-Object | Select-Object -ExpandProperty Count
Write-Host "You have $largeFilesCount large file(s) in $path"

Based on everything we’ve learned up to this point we can now explore this simple example. Read-Host prompts the user with a literal string wrapped in single quotes. The $path variable is loaded with the entry the user provides. Get-ChildItem then finds all the files in that provided path, and loads the results into $rawFileData. We then find the files over 100MB with Where-Object and load those results into $largeFiles. Using Measure-Object and Select-Object in the pipeline, we determine the total count of large file over 100MB. We then display back to the user using Write-Host the total number of large files. Note that on the last line we use double quotes because we have a dynamic variable we want to display.

Common PowerShell Variable Types

[string]    String of Unicode characters

[int]       32-bit integer
[long]      64-bit integer
[decimal]   A 128-bit decimal value
[single]    32-bit floating point number
[double]    64-bit floating point number

[bool]      Boolean True/False

[DateTime]  Date and Time

[array]     An array of values
[hashtable] Hashtable object
Series Navigation<< Getting setup for PowerShell DevelopmentTaking Control with PowerShell Logic >>

Leave a Reply

Your email address will not be published. Required fields are marked *