The Exchange Management Shell and PowerShell define several types of commands that administrators can use in development. These commands include functions, filters, scripts, aliases, and executables (applications). The main command type is a simple, small command called a cmdlet. Both EMS and PowerShell supply sets of cmdlets and fully support cmdlet customization to suit the organization’s environment. The PowerShell/EMS runtime processes all cmdlets.
An EMS cmdlet is a simple set of Exchange Server-specific commands bundled together to interact with a managed application (Exchange Server) and the operating system. It is similar to a built-in command in any other shell, such as Cmd.exe, Bash, or ksh. A conventional shell processes most commands as separate executable programs. Each program must parse the input and parameters, bind values to the correct parameters, format the output, and display the output.
EMS, in contrast, processes commands as instances of .NET classes and objects. The administrator must provide the necessary parameters and values, and then supply details of object types and formatting. EMS does the rest of the work: parsing the parameters and binding them to their values, formatting the output, and then displaying the output.
Cmdlet Examples
The administrator can run a cmdlet singly or as one of several cmdlets piped together on the command line. For example, the single cmdlet:
Get-AddressList
returns all attributes of an address list or set of address lists. The pipelined command :
Get-AddressList | export-csv “C:AddressList.csv”
produces a collection of address lists and pipelines it to the export-csv cmdlet, which requires the file path and name parameter to create a CSV file.
The following example is a custom script line that displays all public folders, their message counts, and total message sizes in a table format:
get-PublicFolder -recurse | get-PublicFolderStatistics | select-object name,itemCount,totalItemSize
Although this is only a single-line command, it can be tedious to type every time it is needed. It can be typed into a text editor and saved as a .ps1 file, PFSize.ps1 for example, in the system path so that it can easily be run again and again.
A working knowledge of .NET is required to write more complex functions that access objects and classes that are not exposed using the built-in cmdlets. The following cmdlet example uses the system.net.mail.smtpClient class in .NET to send a Simple Mail Transfer Protocol (SMTP) email to a nonauthenticating SMTP server using the EMS or PowerShell command line:
$From = “EMStest@companyabc.com”
if ($args.Length -lt 1) {
$To = “administrator@companyabc.com”
}
else {
$To = $args[0]
}
$Subject = “Greetings from EMS!”
$Body = “Hello, this is a test from the Exchange Management Shell.”
$SmtpClient = new-object system.net.mail.smtpClient
$SmtpClient.host = $SmtpServer
$SmtpClient.Send($From, $To, $Subject, $Body)
This cmdlet takes an argument, or parameter. If the cmdlet is saved as TestMail.ps1, the administrator can issue the following command to send a test SMTP email: TestMail testuser@companyabc.com
Combine Functions to Create a Cmdlet Library
As the administrators become more familiar with EMS and using and writing cmdlets, they will begin to build a library of commonly used cmdlets and scripts. It is common to “recycle” similar cmdlets to use for different tasks. Over time, administrators will find useful scripts and concepts from many resources: colleagues, search engines, scripting blogs, newsgroups, and so on.
It is sometimes useful to put all the cmdlets in a common area where other administrators, users, and developers can peruse them and add to the knowledge base. Often, a fellow administrator needs to perform the same task that another administrator has already written. There is no reason to “reinvent the wheel.” A common practice is to create a network or DFS share where administrators and cmdlet developers have modify permissions and other users have read and execute access permissions. Arrange the folder structure based on business needs and technical requirements.
Modifying and Applying Server Cmdlets to Other Systems
After a cmdlet has been written and tested, it is often useful to run the same cmdlet against many or all servers in the organization. For example, consider the following cmdlet that configures the external URL for OWA on SERVER1:
Set-OwaVirtualDirectory -Identity ‘MYSERVERowa (Default Web Site)’ -ExternalUrl ‘https://mail.windows-scripting.info/owa’
It is easy to convert this cmdlet so it will run against all client access servers in the Exchange Server organization using pipelining:
Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -ExternalUrl ‘https://mail.windows-scripting.info/owa’
In this example, Get-OwaVirtualDirectory returns a collection of all the OWA Virtual Directories in the Exchange Server organization and pipes them to the Set-OwaVirtualDirectory cmdlet, where it assigns the value.