If you work with Exchange Server 2010, you’ve probably had to fire up the Exchange Management Shell to perform any number of administrative tasks. You may have used it to provision mailboxes or add users to a distribution group. One aspect that many Exchange admins struggle with, however, is writing reusable scripts and setting up their Exchange Management Shell environments to do so.
Consider everything that needs to be done when provisioning new mailboxes. After you create a mailbox with the New-Mailbox cmdlet, you may need to follow that with the Set-User cmdlet to modify additional Active Directory attributes. Once that’s done, you may need to add the newly created recipient to a distribution group.
These are three separate tasks that can be wrapped up into a reusable .ps1 script. By creating a reusable script, you can easily run it repeatedly and make more efficient use of your time.
Creating and testing reusable PowerShell scripts -- what you’ll need
You can use reusable scripts to tackle complex tasks. This will involve processing a collection of items with a loop or using some kind of conditional logic to determine what to do if a condition triggers as “true.”
Developing, testing and debugging these types of scripts without the help of a true script editor can be frustrating. Notepad.exe is great text editor, but it doesn’t provide syntax highlighting or intellisense for PowerShell code.
There are a number of script editors available. Some are free; others are more robust commercial tools and cost money. I use the PowerShell Integrated Scripting Environment (ISE). It comes with PowerShell v2, is installed on Windows 7 by default and can easily be added onto any other machine that supports PowerShell v2.
Whichever editor you decide to use, you need to get Exchange cmdlets loaded into it. This will help you find all of the available commands and execute them from the editor so that you can test your code.
This is typically done from within a PowerShell profile that executes when you run PowerShell.exe or when the PowerShell engine is hosted in an application -- like the PowerShell ISE. Think of a profile as a logon script for your PowerShell session.
Let’s take a look at an approach that will help get your Exchange Server 2010 environment loaded in a number of scripting editors, as well as your normal PowerShell console.
The first thing to do is look at available profile types. To view them, run the $profile.psextended | Format-List command in a standard PowerShell console or in the Exchange Management Shell. This will return a list of valid profile paths.
I like to use the CurrentUserAllHosts profile type. On my Windows 7 machine, I created my profile using the %userprofile%\Documents\WindowsPowerShell\profile.ps1 file path.
After you’ve created your profile.ps1 script in your desired location, add the initialization commands to get the Exchange cmdlets loaded into your environment.
Loading Exchange Management Shell cmdlets from a profile (remotely)
Something you may come across when perusing code samples on the Web is how to manually load an Exchange snap-in. You may see a command like the following:
In Exchange Server 2007, this was the only way to get cmdlets loaded from a profile or into the traditional shell. Back then, the snap-in had a slightly different name. But even today, loading cmdlets this way requires the Exchange tools to be installed locally.
With Exchange Server 2010, these tools rely on PowerShell remoting. Manually loading the snap-in is not supported. Fortunately, if you have full-blown administrative rights in Active Directory, this should work without a hitch.
You may run into problems, however, if you work in an environment where you have limited Active Directory capabilities and have been delegated specific rights via role-based access control (RBAC). The main issue here is that manually loading the snap-in bypasses PowerShell remoting, which is required to implement Exchange 2010’s RBAC.
One way around this is to manually create a remote session and import the cmdlets from one of your Exchange 2010 servers. The nice thing is you can do this on any machine that has PowerShell v2; even 32-bit workstations where the Exchange 2010 tools cannot be installed.
To start, open the profile you’ve created with notepad.exe, and add the following code. Be sure to replace servername with the name of one of your Exchange 2010 servers:
$s = New-PSSession -ConfigurationName microsoft.exchange `
This technique is referred to as implicit remoting. It builds a dynamic module on the fly. This requires your PowerShell execution policy be set to allow the execution of scripts. You can learn more by running Get-Help about_Execution_Policies.
Loading Exchange Management Shell cmdlets from a profile (locally)
If you are writing scripts from an editor on a machine that has the Exchange 2010 tools installed, I recommend using another approach to get your environment loaded. Open your profile in Notepad.exe and add the following code:
. 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'
This uses a local script that gets installed along with the Exchange tools. The period before the script is what’s known as “sourcing” or “dotting” the script. That’s what makes the subsequent call to Connect-ExchangeServer possible.
Notice that I used the -auto parameter. As you might guess, this locates the best server to use and prevents you from having to hard-code a server name into your profile. This will still load the cmdlets via remote PowerShell, but also gives you a richer experience.
If you set up a profile this way -- depending on the profile type -- it may execute when you start up the Exchange Management Shell (EMS), causing a glut of errors. This happens because cmdlets that are already loaded will try to load again. The best way to handle this is to modify your EMS shortcut, which has its target set to this:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -command ". 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto"
Simply modify the shortcut by adding the -noprofile switch to PowerShell.exe:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -noprofile -command ". 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto"
At this point, your EMS shortcut will still properly load your Exchange environment when it’s time for interactive administration. When you need to author scripts, your profile will load the EMS environment, making commands available in your script editor.
ABOUT THE AUTHOR
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 mikepfeiffer.net, where he blogs regularly about Exchange Server and PowerShell-related topics.