Executive Summary:

Windows PowerShell supports both client-side and server-side filtering for Microsoft Exchange Server 2007 management. Scripts for frequently repeated Microsoft Exchange Server management procedures can be run in batch mode, but you need to call the Exchange Management Shell snap-in. Windows PowerShell supports different levels of security for running scripts.

Windows PowerShell is a powerful management tool for Exchange Server 2007, particularly if you learn to use it efficiently. In "Setting Up Exchange Management Shell," July 3, 2007, InstantDoc ID 96187, I explained how to customize the shell and how to set the correct scope for queries. Now let's look at using filters to limit data sets, how to execute scripts in batch mode, and how execution policies provide security for your shell.

Filters
PowerShell supports server-side and client-side filters. Any time you use the Where-Object cmdlet, you're executing a client-side filter. All PowerShell commands that can filter data support client-side filters. Exchange management is different from standard Windows management because of the potential number of objects you can ask a query to process: It's one thing to ask for all the active processes on a server (at most, a few hundred even on a very large server) and quite another to ask for a list of all the mailboxes on a server (potentially, a few thousand). Therefore, some Exchange cmdlets also support server-side filters.

Client-side filters bring the whole set of requested data from the server to the client before applying the filter; the command then processes the filtered data set. The client and server both do a lot of work to isolate data in such commands. Server-side filters ask the Exchange server to filter the data set and pass only the filtered data to the client for execution, reducing the amount of data that traverses the network for the client to process. Only certain commands that deal with users, other mail-enabled objects, and queues support the server-side -Filter parameter, and not all properties returned by these commands support filtering. Without filters, these commands can generate a huge amount of data in any medium or large organization and be slow to execute.

To see the two filter types in action, consider searching for all mailboxes with “Kent” in their name. You could use either of these commands:

Get-Mailbox `
 -Filter \{Name -like '*Kent*'\} `
 -ResultSize 5000
 
Get-Mailbox `
 -ResultSize 5000 | `
 Where \{$_.Name -like '*Kent*'\}

The -ResultSize parameter limits the size of the collection that Exchange Management Shell processes. Though similar, the queries return very different results:

  • The first query (server-side filter) returns the first 5,000 mailboxes that it finds that include “Kent” in the mailbox name.
  • The second query (client-side filter) fetches data for the first 5,000 mailboxes to the client, then applies the filter to find mailboxes that include “Kent” in the name, which might not find all the mailboxes we want.

With any reasonably sized set of mailboxes, the server-side query has to process significantly more data to find what we asked for, but it executes faster than the client-side filter. When I executed these two commands on an Exchange organization with 170,000 mailboxes, the server-side filter completed in 43 seconds and the client-side filter in 81 seconds.

Server-side filters might appear slower because they provide the results after the server processes all the data: You wait, then see the filtered records all at once. By comparison, the client-side filter fetches and filters data continuously, so you see output on the screen as the command finds each matching record. However, the important indicator of performance is how long the filter takes to complete: Server-side filters are always faster.

Table 1 shows the commands you're most likely to use with server-side filters. The commands for working with user accounts, groups, and mailboxes each support a different set of filterable properties. You can use a query to find the properties of a returned object. For example, the following set of commands

Get-Mailbox -id Redmond | `
 Get-Member | Where-Object `
 \{$_.MemberType -eq 'Property'\}

uses the Get-Mailbox cmdlet to return information about an object. It then pipes the results to the Get-Member cmdlet, which lists the properties supported for the object. Microsoft hasn’t yet documented the full set of properties that support filters. The properties you'll use most commonly, such as Name, Office, and the custom attributes, are supported; less-common attributes, such as IsValid, aren't.

Running Scripts in Batch Mode
You can use PowerShell to write scripts to execute frequently repeated procedures in batch mode. When you write an Exchange management script, you have to call the Add-PSSnapin cmdlet to load the Exchange snap-in so that PowerShell recognizes the Exchange-specific cmdlets. If you wrote a simple script to report on mailbox quotas for everyone in an organization and pipe the output to a text file, it might be something like this:

Get-MailboxServer | `
 Get-MailboxStatistics `
> c:\temp\AllMailboxStats.txt

This command works if you execute it in Exchange Management Shell, but it won't generate anything in batch mode. In fact, PowerShell doesn't provide a command to run scripts in batch, so you have to rely on the Windows scheduler to submit batch files for processing. The batch file calls PowerShell and passes the name of the script as a parameter, as in the following:

PowerShell.Exe
 c:\Script\Get-All-Mailboxes.Ps1

In the script file, we have to tell PowerShell about the Get-MailboxStatistics cmdlet by loading the Exchange snap-in, so the script might look like

Add-PSSnapin 'Microsoft.Exchange.' `
 + 'Management.PowerShell.Admin'
Get-MailboxServer | `
 Get-MailboxStatistics `
 > c:\temp\AllMailboxStats.txt

Adding the Exchange snap-in isn't an intuitive thing to do when designing scripts, but you have to create the same environment for the batch script that you would have when you work with Exchange Management Shell interactively.

Execution Policies
In knowledgeable hands, Exchange Management Shell is a powerful management interface that lets you manipulate objects with just a few lines of code. To control the ability of users to execute shell commands, PowerShell supports execution policies, which define the conditions under which PowerShell loads files for execution.

There are four policies: Restricted, AllSigned, RemoteSigned, and Unrestricted. Table 2 shows the level of security each mode offers. By default, PowerShell runs as Restricted, the most secure mode. In this mode, you can issue PowerShell commands interactively at the shell prompt, but you can't call scripts.

If you attempt to run an unsigned script that doesn't comply with policy, PowerShell signals that it can't load the script. You can sign scripts with the Set-AuthenticodeSignature cmdlet, but you need to get a valid certificate first, which can be one you generate yourself or one you buy from a commercial Certificate Authority (CA).

Learning the Finer Points
Exchange administrators are still getting to know how to use Exchange Management Shell most effectively. It's easy to get familiar with the basic commands, such as Get-Mailbox and Set-Mailbox, but the finer points will take time to figure out. The topics of filters, batch mode, and execution policies should help you use PowerShell more successfully.