Manage Learn to apply best practices and optimize your operations.

How to write reusable PowerShell scripts for Exchange Server

We’ve all heard about the virtues of PowerShell. Reusable scripts may not change your life, but they'll certainly change your job and save you lots of time.

Many of the Exchange admins I know enjoy sharing stories about how PowerShell has completely changed how they do...

their jobs. The thing is, they’re not talking about getting down and dirty in the shell. Many have built reusable scripts they turn to time and again. Don’t worry if you’re not there yet; I can show you how.

Getting started with reusable PowerShell Scripts
Before we start, make sure that you’ve set up your Exchange environment for reusable PowerShell scripts. Now let’s take a routine task as our first example. During mailbox creation, most admins do more than simply run the New-Mailbox cmdlet. You may need to perform other tasks, such as setting additional Active Directory attributes or disabling protocols like ActiveSync, to complete the provisioning process.

Admins may also need to add these newly created recipients to one or more distribution groups. This all requires a lot of pointing and clicking around the Exchange Management Console (EMC). Fortunately, you can accomplish all of this in a fraction of the time with a reusable PowerShell script.

Interactive PowerShell scripts for Exchange
Depending on your requirements, there are a couple of ways to develop reusable scripts. For example, unattended automation may not be a requirement. Maybe you just need a tool that does things in the correct sequence, something that can prompt an operator each step of the way. This eliminates human error and is a breeze to do with a PowerShell script. Take a look at the following code:

$name = Read-Host “Enter a user name”
$upn  = Read-Host “Enter a user principal name”
$alias  = Read-Host “Enter an alias”
$password  = Read-Host “Enter a password” -AsSecureString
$dept = Read-Host “What department is the user in?”
$groupname  = Read-Host “Which group should this user be added to?”

New-Mailbox -Name $name –UserPrincipalName $upn -Alias $alias -Password $password

Set-User $alias –Department $dept

Add-DistributionGroupMember $groupname –Member $alias

As you know, you can take this code and save it in a .ps1 file. When you run the script from the Exchange Management Shell (EMS), the Exchange-specific cmdlets required to do this work are called in sequence.

Notice that the first six lines of the script prompt an operator for information using the Read-Host cmdlet. The dollar sign ($) signifies the start of a variable, which is a place to store the values provided by the operator. The names of these variables were simply chosen at random.

Note: Remember that variables should be unique. Never use them to store any other value.

Most of the values the operator provides are self-explanatory. When you run the Read-Host cmdlet, you supply a prompt, like “Enter a user name,” that the operator will see.

For most of these, we’re storing the input received as simple strings inside a variable that we’ll use later. But one of those variables is not like the others. The $password variable is almost identical, but notice that we’ve captured the input using Read-Host’s -AsSecureString parameter.

This means that instead of storing the value as a simple string, it is encrypted using the .NET framework SecureString class. This is required because the New-Mailbox cmdlet’s -Password parameter requires the value to be this data type.

The remainder of the script is fairly simple. Next, we call the New-Mailbox, Set-User and Add-DistributionGroup cmdlets. Because we’ve saved the input provided by the caller of the script, we can reuse that information to identify the user and the required settings with subsequent commands.

PowerShell scripts for Exchange that accept parameters
Instead of prompting an operator for input, you might instead choose to call your script and assign the required input values as parameters. So, as opposed to running a script called c:\SetupUser.ps1 and answering a bunch of questions, you could do something like this:

$password = ConverTo-SecureString “[email protected]” -AsPlainText -Force

c:\SetupUser.ps1 -Name ‘Dave Smith’ –Upn [email protected] –Alias dsmith –Password $password

You could also call your script from within another script and assign the parameter values using variables that were created based on some other condition:

c:\SetupUser.ps1 –Name $name –Upn $upn –Alias $alias –Password $password

Let’s take the code from our previous example and configure it to accept input values as parameters. This is what it looks like:


$name = Read-Host “Enter a user name”
$upn  = Read-Host “Enter a user principal name”
$alias  = Read-Host “Enter an alias”
$password  = Read-Host “Enter a password” –AsSecureString
$office =  = Read-Host “What office is the user in?”
$groupname  = Read-Host “Which group should this user be added to?”

New-Mailbox –Name $name –UserPrincipalName $upn –Alias $alias –Password $password

Set-User $alias –Office $office

Add-DistributionGroupMember $groupname –Member $alias

This time, the first few lines of the script are a bit different. Notice that we’ve still declared variables for all of the required inputs, but they are enclosed in the parameter block.

This tells PowerShell that the script has parameters that match the names of these variables. Therefore, you could save this code to a .ps1 script and assign the values when executing it.

As you can imagine, the combination of commands that need to be run from a script may vary depending on your requirements. If you’re just starting out, use these examples as a framework for building your own reusable scripts. Simply replace the cmdlets in these examples with whatever cmdlets you need, and come up with your own variables.

Mike Pfeiffer is a Microsoft Certified Master on Exchange 2010 and a Microsoft Exchange MVP. In addition to being an author and IT conference speaker, Mike delivers Exchange, Lync, and PowerShell courses through Interface Technical Training in Phoenix, AZ. You can find many of his thoughts online at, where he blogs regularly about Exchange Server and PowerShell-related topics.

Dig Deeper on Exchange Server setup and troubleshooting