Working With PowerShell Variables
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
- PS1 – Should you learn PowerShell?
- Learn and use PowerShell with just three commands
- Working with the PowerShell Pipeline
- PowerShell History and Current State
- Getting setup for PowerShell Development
- Working With PowerShell Variables
- Taking Control with PowerShell Logic
- PowerShell Input & Output
- PowerShell Errors and Exceptions Handling
- PowerShell Remoting
- PowerShell Scripts
- PowerShell Functions
- Manage Cloud with PowerShell
- PowerShell Modules
Hi,
I am trying to create GUI form and creating a dropdown list. But the values of dropdown list is larger. Is it possible to call the variable with short name (eg: Europe Server canonical name is : “OU=PROD,OU=Citrix,OU=infra,OU=Servers,DC=europe,DC=testsite,DC=com”) I would like to call this value with a short name in the dropdown list as PRODInfra. Is it possible ?
$DropDownBox = New-Object System.Windows.Forms.ComboBox
$DropDownBox.Location = New-Object System.Drawing.Size(20,50)
$DropDownBox.Size = New-Object System.Drawing.Size(180,20)
$DropDownBox.DropDownHeight = 200
$Form.Controls.Add($DropDownBox)
$wksList=@(“OU=PROD,OU=Citrix,OU=infra,OU=Servers,DC=europe,DC=testsite,DC=com”,”OU=PreProd,OU=Citrix,OU=infra,OU=Servers,DC=europe,DC=testsite,DC=com”)
foreach ($wks in $wksList) {
$DropDownBox.Items.Add($wks)
}