Working with variables and objects
Every scripting language makes use of variables as placeholders for data, and PowerShell is no exception. You'll need to work with variables often to save temporary data to an object so you can work with it later. PowerShell is very different from other command shells in that everything you touch is, in fact, a rich object with properties and methods. In PowerShell, a variable is simply an instance of an object just like everything else. The properties of an object contain various bits of information depending on the type of object you're working with. In this recipe we'll learn to create user-defined variables and work with objects in the Exchange Management Shell.
How to do it...
To create a variable that stores an instance of the testuser
mailbox, use the following command:
$mailbox = Get-Mailbox testuser
How it works...
To create a variable, or an instance of an object, you prefix the variable name with the dollar sign ($
). To the right of the variable name, use the equals (=
) assignment operator, followed by the value or object that should be assigned to the variable. Keep in mind that the variables you create are only available during your current shell session and will be destroyed when you close the shell.
Let's look at another example. To create a string variable that contains an e-mail address, use the following command:
$email = "testuser@contoso.com"
Tip
In addition to user-defined variables, PowerShell also includes automatic and preference variables. To learn more, run Get-Helpabout_Automatic_Variables
and Get-Helpabout_Preference_Variables
.
Even a simple string variable is an object with properties and methods. For instance, every string has a Length
property that will return the number of characters that are in the string:
[PS] C:\>$email.length 20
When accessing the properties of an object, you can use dot notation to reference the property with which you want to work. This is done by typing the object name, then a period, followed by the property name, as shown in the previous example. You access methods in the same way, except that the method names always end with parenthesis ().
The string data type supports several methods, such as Substring
, Replace
, and Split
. The following example shows how the Split
method can be used to split a string:
[PS] C:\>$email.Split("@") testuser contoso.com
You can see here that the Split
method uses the "@"
portion of the string as a delimiter and returns two substrings as a result.
Tip
PowerShell also provides a -Split
operator that can split a string into one or more substrings. Run Get-Helpabout_Split
for details.
There's more...
At this point, you know how to access the properties and methods of an object, but you need to be able to discover and work with these members. To determine which properties and methods are accessible on a given object, you can use the Get-Member
cmdlet, which is one of the key discovery tools in PowerShell along with Get-Help
and Get-Command
.
To retrieve the members of an object, pipe the object to the Get-Member
cmdlet. The following command will retrieve all of the instance members of the $mailbox
object we created earlier:
$mailbox | Get-Member
Tip
To filter the results returned by Get-Member
, use the -MemberType
parameter to specify whether the type should be a Property
or a Method
.
Let's take a look at a practical example of how we could use Get-Member
to discover the methods of an object. Imagine that each mailbox in our environment has had a custom MaxSendSize
restriction set and we need to record the value for reporting purposes. When accessing the MaxSendSize
property, the following information is returned:
[PS] C:\>$mailbox.MaxSendSize IsUnlimited Value ----------- ----- False 10 MB (10,485,760 bytes)
We can see here that the MaxSendSize
property actually contains an object with two properties: IsUnlimited
and Value
. Based on what we've learned, we should be able to access the information for the Value
property using dot notation:
[PS] C:\>$mailbox.MaxSendSize.Value 10 MB (10,485,760 bytes)
That works, but the information returned contains not only the value in megabytes, but also the total bytes for the MaxSendSize
value. For the purpose of what we are trying to accomplish, we only need the total megabytes. Let's see if this object provides any methods that can help us out with this using Get-Member
:
From the output shown in the previous screenshot, we can see this object supports several methods that can be used convert the value. To obtain the MaxSendSize
value in megabytes, we can call the ToMB
method:
[PS] C:\>$mailbox.MaxSendSize.Value.ToMB() 10
In a traditional shell, you would have to perform complex string parsing to extract this type of information, but PowerShell and the .NET Framework make this much easier. As you'll see over time, this is one of the reasons why PowerShell's object-based nature really outshines a typical text-based command shell.
An important thing to point about this last example is that it would not work if the mailbox had not had a custom MaxSendSize
limitation configured. Nevertheless, this provides a good illustration of the process you'll want to use when you're trying to learn about an object's properties or methods.
Variable expansion in strings
As mentioned in the Understanding command syntax and parameters recipe in this chapter, PowerShell uses quoting rules to determine how variables should be handled inside a quoted string. When enclosing a simple variable inside a double-quoted string, PowerShell will expand that variable and replace the variable with the value of the string. Let's take a look at how this works by starting off with a simple example:
[PS] C:\>$name = "Bob" [PS] C:\> "The user name is $name" The user name is Bob
This is pretty straightforward. We stored the string value of "Bob"
inside the $name
variable. We then include the $name
variable inside a double-quoted string that contains a message. When we hit return, the $name
variable is expanded and we get back the message we expect to see on the screen.
Now let's try this with a more complex object. Let's say that we want to store an instance of a mailbox object in a variable and access the PrimarySmtpAddress
property inside the quoted string:
[PS] C:\>$mailbox = Get-Mailbox testuser [PS] C:\>"The email address is $mailbox.PrimarySmtpAddress" The email address is test user.PrimarySmtpAddress
Notice here that when we try to access the PrimarySmtpAddress
property of our mailbox object inside the double-quoted string, we're not getting back the information that we'd expect. This is a very common stumbling block when it comes to working with objects and properties inside strings. We can get around this using sub-expression notation. This requires that you enclose the entire object within $()
characters inside the string:
[PS] C:\>"The email address is $($mailbox.PrimarySmtpAddress)" The email address is testuser@contoso.com
Using this syntax, the PrimarySmtpAddress
property of the $mailbox
object is properly expanded and the correct information is returned. This technique will be useful later when extracting data from objects and generating reports or logfiles.
Strongly typed variables
PowerShell will automatically try to select the correct data type for a variable based on the value being assigned to it. You don't have to worry about doing this yourself, but we do have the ability to explicitly assign a type to a variable if needed. This is done by specifying the data type in square brackets before the variable name:
[string]$a = 32
Here we've assigned the value of 32
to the $a
variable. Had we not strongly typed the variable using the [string]
type shortcut, $a
would have been created using the Int32
data type, since the value we assigned was a number that was not enclosed in single or double quotes. Take a look at the following screenshot:
As you can see here, the $var1
variable is initially created without any explicit typing. We use the GetType()
method, which can be used on any object in the shell, to determine the data type of $var1
. Since the value assigned was a number not enclosed in quotes, it was created using the Int32
data type. When using the [string]
type shortcut to create $var2
with the same value, you can see that it has now been created as a string.
It is good to have an understanding of data types because when building scripts that return objects, you may need to have some control over this. For example, you may want to report on the amount of free disk space on an Exchange server. If we store this value in the property of a custom object as a string, we lose the ability to sort on that value. There are several examples throughout the book that use this technique.
See Appendix A, Common Shell Information, for a listing of commonly-used type shortcuts.