Scripting with the Exchange Management Shell
Applies to: Exchange Server 2007, Exchange Server 2007 SP1, Exchange Server 2007 SP2, Exchange Server 2007 SP3
Topic Last Modified: 2009-12-18
For most general tasks, running cmdlets one at a time or together through pipelines is sufficient. However, sometimes you may want to automate tasks. The Exchange Management Shell supports a very rich scripting language, based on the Microsoft .NET Framework, which resembles the scripting language in other shells. The Exchange Management Shell lets you create scripts, from the very simple to the very complex. Language constructs for looping, conditional, flow-control, and variable assignment are all supported.
Every organization has tasks that are in some way unique to that organization. With a library of script files to perform these tasks, administrators can save time and run these scripts on any computer that has the Exchange Management Shell installed.
For more information about how to use scripts, see Scripting with Windows PowerShell. Because the Exchange Management Shell is built on Microsoft Windows PowerShell technology, the scripting guidance for Windows PowerShell applies to the Exchange Management Shell.
Those familiar with the Cmd.exe environment know how to run command shell scripts. These are nothing more that text files that have the .bat file name extension. Like batch files, you can create the Exchange Management Shell script files by using a text editor, such as Notepad. The Exchange Management Shell script files use the .ps1 file name extension.
The Exchange Management Shell uses a root directory for script files when they are called. By default, the root directory is the
<root drive>:\Program Files\Microsoft\Exchange Server\bin directory. You can also verify the current
PSHome directory on any computer that is running the Exchange Management Shell by running
$PSHome from the command line. Both of these directories are in the PATH environment variable.
If a script file is saved to the root directory, you can call it by using the script name. If the script file is located somewhere other than the current location, the path and script name must be used. If the script file is located in the current location, the script name must be prefixed by
The following examples show the command syntax requirements for calling three different scripts. These examples all use the Get-Date cmdlet, from three different locations.
[PS] C:\>Get-Date-Script-A.ps1 Friday, January 20, 2006 3:13:01 PM
The script file
Get-Date-Script-A.ps1 is located in the directory that is specified by
$PSHhome and requires only the script name to run.
[PS] C:\>c:\workingfolder\Get-Date-Script-B.ps1 Friday, January 20, 2006 3:13:25 PM
The script file
Get-Date-Script-B.ps1 is located in the
C:\workingfolder directory so the full path must be supplied to run.
[PS] C:\>.\Get-Date-Script-C.ps1 Friday, January 20, 2006 3:13:40 PM
The script file
Get-Date-Script-C.ps1 is located in the current location,
C:\. Therefore, it must be prefixed with
.\ to run.
[PS] C:\>Get-Date-Script-C.ps1 'Get-Date-Script-C.ps1' is not recognized as a Cmdlet, function, operable program, or script file. At line:1 char:21 + Get-Date-Script-C.ps1 <<<<
In the last example, when this same script,
Get-Date-Script-C.ps1, is called without the prefix
.\, the expected results are shown.
As a best practice, always give script files a descriptive name and include comments in the script to describe its purpose and to identify each point of interest. Some information about the author should also be included in case someone who is running the script has questions about its use. Use the pound symbol (
#) to start comment lines inside the script body.
If you want to run a script on a scheduled basis by the Windows Task Scheduler service, you can call the Exchange Management Shell and include the script that you want to run as a parameter. Because the Exchange Management Shell is a snap-in of the Windows PowerShell, you must also load the Exchange Management Shell snap-in when you run the command in order to run any Exchange -related cmdlets. The following syntax is required to load the Exchange Management Shell snap-in and run your script from the Cmd.exe command:
PowerShell.exe -PSConsoleFile "C:\Program Files\Microsoft\Exchange Server\Bin\ExShell.Psc1" -Command ". '<Path to Your Script>'"
For example, to run the script
C:\My Scripts, use the following command:
PowerShell.exe -PSConsoleFile "C:\Program Files\Microsoft\Exchange Server\Bin\ExShell.Psc1" -Command ". 'C:\My Scripts\RetrieveMailboxes.ps1'"
For additional options to use when you call the Exchange Management Shell from the Cmd.exe environment, type PowerShell.exe /?
In Microsoft Exchange Server 2007, you can use the Exchange Management Console to view detailed information about specific Exchange Management Shell commands that are used to perform certain tasks. When you run a wizard in the Exchange Management Console, the wizard takes the information that you entered and creates an Exchange Management Shell command that is then run by the computer. You can copy and paste this command directly into the Exchange Management Shell or copy it into a text editor where you can modify it. If you examine how the Exchange Management Console creates commands, you can obtain a better understanding of how to construct or modify those commands to suit your future needs.
For example, if you create a new mailbox for a person named Frank Lee, the following information is displayed on the Completion page of the New Mailbox wizard:
Figure 1 New Mailbox wizard completion page
The information that is displayed on the Completion page gives you an idea of the information that you must have to make sure a similar command that you run in the Exchange Management Shell is completed successfully. On the Completion page, press CTRL+C to copy this information to the Clipboard. Then you can use a text editor to examine the command to determine what must be changed to add more mailboxes. You can also customize the command so that it can be used as part of a script that consumes a comma-separated-values (CSV) file or another input source to automate creating many mailboxes.
When you create new scripts, you should always test them in a lab environment before you apply them in your production environment. As you test your scripts in your lab, and as you deploy them in your production environment, you can use the WhatIf parameter that is available on many cmdlets included in the Exchange Management Shell to verify that your script performs as expected. The WhatIf parameter instructs the command to which it is applied to run, but only to display which objects would be affected by running the command and what changes would be made to those objects, without actually changing any of those objects.
For more information about the WhatIf parameter, see WhatIf, Confirm, and ValidateOnly Parameters.
Scripts may not work as expected for many reasons. It can be difficult to determine where the problem is and what is going wrong. The Exchange Management Shell can help you locate general syntax errors by reporting the line and character at the point of failure. When the syntax of a script is correct but its behavior is unexpected, it can be much more difficult to diagnose the problem. The Exchange Management Shell includes simple debugging functionality to troubleshoot script files by examining each step that the script makes as it executes. This functionality is called tracing.
To enable tracing and examine each command step in a script, use the Set-PSDebug cmdlet with the Trace parameter set to a value of
1. To examine each step and each variable assignment as they are made, set the Trace parameter to a value of
2. To turn tracing off, set the value of the Trace parameter to
To examine each command in a script line by line, use the Set-PSDebug cmdlet with the Step parameter. At each step, you will be prompted to continue the operation. The following choices are available in
[Y] Yes (continue to the next step) [A] Yes to All (continue to the end of the script) [N] No (stop this step) [L] No to All (stop all remaining steps) [S] Suspend (suspend at this point and drop to a prompt)
Suspend lets you exit to a prompt where you can run any command, for example, to check or set values on an object before the script can access it. When you are ready to resume script execution, type Exit and control immediately returns to the point at which the script was suspended.