Variables are a fundamental part of Windows PowerShell. They're quite different from the variables in Cmd.exe. In Cmd.exe, all variables are environment variables, which you primarily access with the Set command. The environment variables can store only strings of text. (You can store a number in an environment variable, but it's up to the program that's reading the environment variable to interpret it as a number.)
The variables in PowerShell aren't environment variables but rather native PowerShell variables. They can store much more than just text. In fact, PowerShell variables store objects (specifically, Microsoft .NET Framework objects). For example, a PowerShell variable can contain a String object or a number object, such as an Int (integer) object. Objects provide an extraordinary amount of flexibility.
In PowerShell, variable names start with the $ character. You can assign a value to a variable using the assignment operator, which is the = character. You can create a variable by simply assigning it a value. For example, the command
- $myName = "Ferb"
creates a variable named $myName and assigns it a string value. The double quotes (" ") indicate that a string value is being assigned to the variable.
As I mentioned previously, PowerShell variables are really objects. In simple terms, objects can contain data (properties) and operations you can perform on the data (methods). In this example, the $myName variable is really a String object. As with other objects, the String object has both properties and methods. For example, the Length property of a String object tells you the number of characters in the string, and the ToUpper method gives you a copy of the string converted to uppercase. You can access both properties and methods using a dot (.) after the variable name. Properties don't use parentheses ( ), but methods do. For example, the command
returns a value of 4 because the variable's value (Ferb) is four characters long. The command
Discovering an Object's Type, Properties, and Methods
The properties and methods that an object can use depend on the object's type. For example, a String object has different properties and methods than an Int object. You can get a variable's object type by calling its GetType method like this:
As Figure 1 shows, the $myName variable contains a String object. (In this introductory discussion, I won't talk about the IsPublic, IsSerial, and BaseType columns.)
Besides using the GetType method to find out the kind of object a variable contains, you can also use the Get-Member cmdlet to see what properties and methods are available. For example, if you run the command
- Get-Member –InputObject $myName
you'll find that 35 properties and methods are available. Figure 2 shows a few of them.
As you've seen, variables can store a single object (e.g., a String or Int object). Variables can also store multiple objects, which are referred to as a collection or an array. For example, the command
- $items = Get-ChildItem
uses the Get-ChildItem cmdlet to retrieve the collection of file system objects in the current directory (i.e., the directory from which you're running the command) and stores that collection in the variable $items.
Introducing Variable Interpolation
When you include a variable's name inside a double-quoted string, PowerShell replaces the variable's name with its value in the string. This is called variable interpolation. For example, if you run the commands
- $myName = "Ferb"
- "Hello, $myName"
you'll receive the result Hello, Ferb.
If the variable you're expanding isn't a string, PowerShell will do its best to coerce the variable's value into a string representation. In addition, PowerShell doesn't perform variable interpolation for single-quoted strings, so you can use single-quoted strings when you don't want PowerShell to replace variables in a string.
A common problem when using variable interpolation is when you want to include an object's property (or the result of an object's method) in the string. Using the standard dot notation to retrieve the property doesn't quite work as expected. For example, the command
- "$myName is $myName.Length characters"
returns the incorrect result of Ferb is Ferb.Length characters.
To work around this problem, PowerShell provides the subexpression operator, $( ), which you can use within the string to get the desired result. For example, the command
- "$myName is $($myName.Length) characters"
returns the correct result of Ferb is 4 characters.
In general, if PowerShell isn't replacing a variable in a double-quoted string like you expect it to, you can put the variable inside $( ) to work around the problem.
Exploring Automatic and Preference Variables
PowerShell provides the Variable: drive, which lets you access the variables in your PowerShell session. The Variable: drive is just like a file system drive (e.g., C), except you're accessing variables instead of file system items. For example, this command lists all variables in your current session:
- Get-ChildItem Variable:
When you run this command, you'll see a list of variables and their values. Initially, these variables are all automatic variables (which store something about PowerShell's state) and preference variables (which store PowerShell user preferences). You can't change the values of automatic variables, but you can change the values of preference variables.
Automatic variables tell you something about PowerShell's current state. For example, the $PWD automatic variable contains PowerShell's current location. Consider the commands and their output in Figure 3.
The $PWD variable contains an object, and the first command retrieves the value of its Path property. At this point, the value is C:\. The next command uses the Set-Location cmdlet to change the current location to the Variable: drive. Note that the Path property of the $PWD variable reflects the change automatically (hence the term automatic). But just for verification, the third command again retrieves the value of the $PWD variable's Path property, which is Variable:\ this time. The last command sets the current location back to the C drive.
Preference variables let you change a user preference within PowerShell. One of the most common preference variables is $ErrorActionPreference, which lets you configure how PowerShell should respond to non-terminating errors. (Non-terminating errors don't prevent the cmdlet from continuing.) By default, $ErrorActionPreference is set to Continue, which means PowerShell will output the non-terminating error and the cmdlet will continue running. Sometimes you might want to have the cmdlet stop as soon as it encounters an error, in which case you'd run the command:
- $ErrorActionPreference = "Stop"
Other times, you might not care about non-terminating errors, so you just want to suppress them altogether with this command:
- $ErrorActionPreference = "SilentlyContinue"
Note that using the $ErrorActionPreference variable has the same effect as using the -ErrorAction cmdlet parameter. The difference is that the -ErrorAction cmdlet parameter affects only a single cmdlet, whereas the $ErrorActionPreference variable affects all cmdlets.
Exploring Environment Variables
PowerShell provides the Env: drive, which lets you access environment variables. In PowerShell, environment variables get copied from the parent process (i.e., the program that started the current PowerShell session). Typically, the initial values of the environment variables are the same as those in Control Panel. (You can use a PowerShell profile script to change the initial values of environment variables so that they don't match the values in Control Panel, but that's beyond the scope of this discussion.)
To view all environment variables in the current PowerShell session, you can run the command:
- Get-ChildItem Env:
This is equivalent to running the Set command in Cmd.exe.
In Cmd.exe, you can surround a string with % characters (e.g., %ALLUSERSPROFILE%), which tells Cmd.exe to replace the variable's name with its value. PowerShell doesn't use the % characters to get the values of environment variables. In PowerShell, you can access an environment variable's value two ways. First, you can access it from the Env: drive directly using the syntax $Env:name, where name is the environment variable's name. For example, if you want to find out the value of ALLUSERSPROFILE, you'd run the command
which returns C:\ProgramData. Alternatively, you can use the Get-Item cmdlet to retrieve the value of an environment variable from the Env: drive. In this case, you don't use the $ character, as shown here:
- Get-Item Env:ALLUSERSPROFILE
The first syntax ($Env:name) is the most common and works when using variable interpolation in double-quoted strings. For example, the command
- "The ALLUSERSPROFILE variable is $Env:ALLUSERSPROFILE"
returns The ALLUSERSPROFILE variable is C:\ProgramData.
Getting Help with Variables
The PowerShell Help system provides quite a bit of information about variables. I recommend that you take a look at the following Help topics: about_Variables, about_Automatic_Variables, about_Preference_Variables, and about_Environment_Variables. To read these Help topics online, you can follow this syntax: help topic, where topic is the topic you want to display. For example, if you want to read the about_Variables topic, you'd run the command:
- help about_Variables
If you're running PowerShell 3.0 and you get an error message when trying to display a Help topic, you'll need to download the Help topics first. To do this, start PowerShell as an administrator by right-clicking the PowerShell shortcut icon and choosing Run as administrator. At the PowerShell prompt, type the command:
Your computer must have a working Internet connection to be able to download the Help topics.
Get a Grip on PowerShell Variables
Understanding PowerShell variables is important because variables are such an integral part of how PowerShell works. Although this brief introduction doesn't explain all there is to know about PowerShell variables, the information presented here provides the essentials you need to understand.