The
Exchange Management Console contains many built-in cmdlets.
Administrators can create their own scripts using the PowerShell ISE or a
common text editor by using one or more cmdlets, which typically
execute in order. The script is stored in a text file with a .PS1 extension.
The PowerShell
common language runtime is an interpretive environment, meaning that
cmdlets, functions, and scripts are loaded into random access memory
(RAM), where they are validated and executed. In EMS, this is performed
on the Exchange server.
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 discussed in this article 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.
Demonstrating 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
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:
$SmtpServer = "server1.companyabc.com"
$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
The book Script the World Using PowerShell is a good resource for more detail on writing scripts using cmdlets.
Combining 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 'SERVER1\owa (Default Web Site)' -ExternalUrl 'https://mail.companyabc.com/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.companyabc.com/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.