Scripting with the Exchange Management Shell
Applies to: Exchange Server 2013
Topic Last Modified: 2012-10-17
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 rich scripting language, based on the Microsoft .NET Framework, which resembles the scripting language in other shells. The Shell lets you create scripts, from simple to 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, you can save time by running these scripts on any computer that has the Shell installed.
For more information about how to use scripts, see Scripting with Windows PowerShell. Because the 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 scripts are simply text files that have the .bat file name extension. Like batch files, you can create the Shell script files by using a text editor, such as Notepad. You can also use the Windows PowerShell Integrated Scripting Environment (ISE) to write scripts. The Windows PowerShell ISE provides a rich editing experience with debugging support, syntax coloring, selective execution, and more. The Shell script files use the .ps1 file name extension.
The 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\V15\bin directory. You can also verify the current PSHome directory on any computer running the Shell by running
$PSHome at a command prompt. 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 period backslash (.\) characters.
These 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 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 The term 'Get-Date-Script-C.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:22 + Get-Date-Script-C.ps1 <<<< + CategoryInfo : ObjectNotFound: (Get-Date-Script-C.ps1:String) , CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
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 running the script has questions about its use. Use the number sign (#) to start comment lines inside the script body.
If you want to run a script on a scheduled basis using the Windows Task Scheduler service, you can call the Shell and include the script that you want to run as a parameter. If you want to use Exchange cmdlets with your script, you must direct Windows PowerShell to connect to a server running Exchange and load the Exchange cmdlets you have access to. The shortcut you use to open the Shell does this automatically. To do this when you want to run a script that contains Exchange cmdlets, you must direct Windows PowerShell to run the scripts that make this connection. This syntax is required to open Windows PowerShell, connect to an Exchange server, and run your script from the Cmd.exe command.
PowerShell.exe -command ". 'D:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; <path to your script>"
This example runs the script RetrieveMailboxes.ps1 from C:\My Scripts.
PowerShell.exe -command ". 'D:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; C:\My Scripts\RetrieveMailboxes.ps1"
For additional options to use when you call the Shell from the Cmd.exe environment, type PowerShell.exe /?
When you create 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's available on many cmdlets included in the 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 switches.
Scripts may not work as expected for many reasons. It can be difficult to determine where the problem is and what's wrong. The 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 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 step mode.
[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.