A Step Beyond Exchange Management Shell Primer

There are many excellent introductory materials covering the Exchange Management Shell in Exchange Server 2007. This article aims to enforce the fundamentals with practical and useful examples. The goal is to help an Exchange administrator better his understanding and command of the EMS in performing routine messaging and related tasks, freeing up time for more important tasks.

What Is The Exchange Management Shell?
The Exchange Management Shell is the command line interface counterpart to the graphical front-end exposed in the Exchange Management Console. The latter is available as a standard Microsoft Management Console snap-in. In a similar fashion, the EMS actually takes the form of a snap-in hosted by PowerShell. Exchange Server 2007 is the first product to ship a customized snap-in for Windows PowerShell. Ultimately, the .NET Framework is the underlying object-oriented platform that provides PowerShell with the capability to work with objects (structured data) instead of plain text only. This fact must be understood in order to harness the real power in the shell, even though only textual information is presented in the PowerShell console.

Before the actual Exchange 2007 setup can begin, the prerequisites stipulate that both the MMC 3.0 and PowerShell RTW 1.0 components be installed. Once you get pass this and complete the standard Exchange installation, the EMS can be accessed via All Programs | Microsoft Exchange Server 2007 | Exchange Management Shell.

If you run the Get-PSSnapin cmdlet from within PowerShell and EMS, you will find that the Exchange snap-in for PowerShell shows up like this:

[PS] C:\>Get-PSSnapin

Name : Microsoft.PowerShell.Core
PSVersion : 1.0
Description : This Windows PowerShell snap-in contains Windows PowerShell manag
ement cmdlets used to manage components of Windows PowerShell.

Name : Microsoft.PowerShell.Host
PSVersion : 1.0
Description : This Windows PowerShell snap-in contains cmdlets used by the Wind
ows PowerShell host.

Name : Microsoft.PowerShell.Management
PSVersion : 1.0
Description : This Windows PowerShell snap-in contains management cmdlets used
to manage Windows components.

Name : Microsoft.PowerShell.Security
PSVersion : 1.0
Description : This Windows PowerShell snap-in contains cmdlets to manage Window
s PowerShell security.

Name : Microsoft.PowerShell.Utility
PSVersion : 1.0
Description : This Windows PowerShell snap-in contains utility Cmdlets used to
manipulate data.

Name : Microsoft.Exchange.Management.PowerShell.Admin
PSVersion : 1.0
Description : Admin Tasks for the Exchange Server

[PS] C:\>

Although the Microsoft.Exchange.Management.PowerShell.Admin snap-in appears to be missing from the standard PowerShell configuration, you’ll find that the snap-in is already registered on a system with Exchange 2007 installed. This can be confirmed as follows:

PS C:\>Get-PSSnapin -Registered

Name : Microsoft.Exchange.Management.PowerShell.Admin
PSVersion : 1.0
Description : Admin Tasks for the Exchange Server

To manually add this to the current PowerShell session, use the Add-PSSnapin cmdlet:

PS C:\>Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin

Add-PSSnapin will load automatically from “%ProgramFiles%\Microsoft\Exchange Server\bin\exshell.psc1". The .psc1 file extension signifies a customized shell for this Exchange PowerShell snap-in that is picked up from $env:path. Without taking this explicit step, any attempt to execute Exchange cmdlets, such as Get-User in the PowerShell session, will result in red-colored error messages alerting you to this fact:

PS C:\>Get-Mailbox
The term 'Get-Mailbox' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
At line:1 char:11
+ Get-Mailbox <<<<

Although you can now run most Exchange specific cmdlets in addition to standard cmdlets from within the PowerShell session, you still miss out on a number of EMS-specific extensions, such as Get-ExCommand, and new aliases. This is because additional commands and settings are loaded as part of the EMS configured by the Exchange setup program as defined in Exchange.ps1. By reviewing the properties of EMS, you will understand how the customized shell is actually built:

%windir%\system32\WindowsPowerShell\v1.0\PowerShell.exe -PSConsoleFile "%ProgramFiles%\Microsoft\Exchange Server\bin\exshell.psc1" -noexit -command ". '%ProgramFiles%\Microsoft\Exchange Server\bin\Exchange.ps1'"

Therefore, I recommend that you stick with the standard EMS to perform Exchange specific tasks on the command-line to avoid confusion and unneeded frustration. As you can see, PowerShell cmdlets are fully accessible from within EMS, but the reverse is not always the case.

Verb-Noun Pair
The verb-noun pair that describes a cmdlet is built in such as way that the noun is always expected to be singular. Nevertheless, this standard naming convention is only a guideline from the PowerShell design team and cannot be easily enforced. The result is that there are quite a number of inconsistencies in the EMS implementation, probably named as such as most of them are commonly used in the plural form in the English language, even though the singular forms exist. Table 1 lists the pairs.

Table 1. Verb-Noun cmdlets ending with “s” in EMS (plural and singular).
Plural Verb-Noun Pair Singular Verb-Noun Pair

Disable-AntispamUpdates
Enable-AntispamUpdates

Get-ActiveSyncDeviceStatistics

Get-AntispamUpdates

Get-ImapSettings
Get-LogonStatistics
Get-MailboxCalendarSettings
Get-MailboxFolderStatistics
Get-MailboxStatistics
Get-ManagedContentSettings
Get-PopSettings

Get-PublicFolderStatistics

Get-UMActiveCalls

New-ManagedContentSettings
Remove-ManagedContentSettings

Set-ImapSettings
Set-MailboxCalendarSettings
Set-ManagedContentSettings
Set-PopSettings

Test-OutlookWebServices

Export-Alias

Get-Alias

Get-ClusteredMailboxServerStatus

 

 

 

Get-Process

Get-StorageGroupCopyStatus

Import-Alias
New-Alias

Set-Alias

 

Stop-Process

Write-Progress

Except for Get-ClusteredMailboxServerStatus and Get-StorageGroupCopyStatus, all other cmdlets in the singular verb-noun pair column come directly from PowerShell itself. The others form part of a discrepancy group that somewhat adds to the learning curve of EMS. Fortunately, the list is not overly exhaustive to make learning them insurmountable.

To retrieve and save a copy of this list, you can use:

Get-Command -noun *s | Format-List name > “C:\Get-EmsListPlural.txt”

Notice the familiar greater-than sign, which is supported as a redirection character. The PowerShell equivalent would be Out-File, as in this example:

Get-Command -noun *s | Format-List name | Out-File “C:\Get-EmsListPlural.txt”

Provisioning Mailbox-enabled Users
By far the most common task for an IT administrator is to create a new Active Directory user account in the domain and enable the corresponding Exchange mailbox at the same time. Here, the New-Mailbox cmdlet is suitable for the task when executed in EMS:

New-Mailbox -Database "Mailbox Database" `
-UserPrincipalName [email protected] `
-Name barryz -OrganizationalUnit ITAdmin

The backwards apostrophe clearly indicates to PowerShell that the statement is incomplete and continues on the next line. This is also the same escape character used to define escape sequences such as a new line, `n, or tab, `t.

This one-liner assumes a default installation of Exchange 2007, where there is a single storage group “First Storage Group” and “Mailbox Database” is the only information store (database) saved as “%ProgramFiles%\Microsoft\ Exchange Server\Mailbox\First Storage Group\Mailbox Database.edb”. You can specify exactly the name of a database to house the user mailbox using the -database parameter such as “Executive Storage Group\Executive Mailbox Database”. Prefixing with the name of a storage group to qualify the database is a valid entry, but this is not documented in the on-line help.

If you summon help for this cmdlet via Get-Help New-Mailbox, you will observe that there are many more parameters that you can supply. Most of them are optional and this example here shows the minimum needed in order to run the cmdlet and provision a mailbox-enabled user successfully.

As soon as you execute the cmdlet, you will be prompted to punch in a password for this account that must conform to the security policies established in the AD domain. Otherwise, you will be hit with an error message and neither the account nor the mailbox will be created:

[PS] C:\>New-Mailbox -Database "Mailbox Database" –UserPrincipalName [email protected] -Name barryz -OrganizationalUnit ITAdmin

cmdlet New-Mailbox at command pipeline position 1
Supply values for the following parameters:
Password:
New-Mailbox : Active Directory operation failed on EX2K7.swissitpro.loc. This error is not retriable. Additional information: Unable to update the password. The value provided for the new password does not meet the length, complexity, or history requirement of the domain.
Active directory response: 0000052D: SvcErr: DSID-031A0FC0, problem 5003 (WILL_
NOT_PERFORM), data 0
At line:1 char:12
+ New-Mailbox <<<< -Database "Mailbox Database" –UserPrincipalName [email protected] -Name barryz -OrganizationalUnit ITAdmin

[PS] C:\>

Because only the minimal amount of information was provided, other essential data that formally identify the user, such as first name and last name, are missing. At the same time, you will see that a number of the user attributes have been automatically filled in for you. These include the display name, user logon name and user logon name (pre-Windows 2000) that have been populated with the same information passed to the -Name parameter of the New-Mailbox cmdlet.

In order to modify the mailbox-enabled user’s attributes, you need to use the Set-User cmdlet separately:

Set-User -Identity barryz -Firstname Barry -LastName Zaky `
-DisplayName "Barry Zaky" -Office "Zurich" `
-Phone "+41 (044) 777 7777"

After executing this cmdlet, the corresponding user attributes will be modified and will show up in the correct fields when inspected using Active Directory Users and Computers snap-in (see Figure 1). These settings are also automatically propagated to the user’s mailbox as seen from the Exchange Management Console (Figure 2).

ADUC Set-User cmdlet
Figure 1. Result of using Set-User cmdlet in ADUC....

 

EMC Set-User cmdlet
Figure 2. ...and in the EMC

You may be surprised to learn that no tabs are available for Exchange-specific settings for a user within ADUC. They are now configurable only from within the EMC in Exchange 2007, where the design is reminiscent of Exchange 5.5 days. That is to say, you will have to manage Exchange and AD settings using distinct graphical tools (unless, of course, you are using EMS).

Still, you can always check the properties of the newly provisioned mailbox at the command-line with Get-Mailbox as shown:

[PS] C:\>Get-Mailbox barry*

Name    Alias   ServerName  ProhibitSendQuota
----    -----   ----------  ---------------
barryz  barryz  ex2k7       unlimited

You can limit the scope of user mailboxes based on a number of criteria such as server, AD organizational unit or specific information store by appending the appropriate parameter. For example, Get-Mailbox -database “SG2\MBX1” to list only user mailboxes found in the named store or Get-Mailbox -server “Ex2k7” to compile a list of all mailboxes on the server. It is worthwhile to note that running Get-Mailbox by itself will return all mailboxes in the entire Exchange organization.

User specific attributes can be queried by running the Get-User cmdlet:

[PS] C:\>Get-User barryz

Name   RecipientType
----   -------------
barryz UserMailbox

In any case, you can always pipe the output to Select-Object to retrieve more detail information such as:

Get-Mailbox barry* | Select-Object *

or send it down to one of the Format-* cmdlets, as in:

Get-Mailbox barry* | Format-List name, firstname, lastname

(The asterisk * signifies a wildcard character.)

Putting It Together
Even with this very humble beginning armed with only the basics, you can already automate the bulk creation of new mailbox-enabled users in your organization. The real power comes from combining all these one-liners into a PowerShell script saved with the .ps1 file extension.

Listing 1: New-UserFromCSVFile.ps1.
# New-UserFromCSVFile.ps1

$users = Import-Csv ".\users.csv"

$ou = "ITAdmin"
$password = "hElLo2Wo$11d"

$spassword = Convertto-Securestring -string $password -asPlainText -force

$users | foreach {
$upn = $_.'Logon Name'+"@swissitpro.loc"
New-Mailbox -Database "EX2k7\First Storage Group\Mailbox Database" `
-OrganizationalUnit $ou -UserPrincipalName $upn `
-Name $_.'Logon Name' -Firstname $_.'Given Name' `
-Lastname $_.'Surname' `
-Password $spassword -ResetPasswordOnNextLogon $true
}

The script begins by retrieving a list of users from a comma-separated file (.csv) in one go, using the Import-Csv cmdlet. The contents are assigned to the users variable (identified with the $ character) where each line of text is stored as an array of string objects. A .csv file uses the first row to identify data in the respective columns (metadata). This is required to identify the particular “slot” in the array you are interested in. For instance, $users[2].’Given name’ will return the value Watson (first element of a string object always begins with zero). You must enclose the text in quotes whenever a space exists.

Table 2. Comma-separated list of new users (users.csv)
Logon Name,Given Name,Surname
dankyd,Danky,Daniels
sweenyc,Sweeny,Conssiti
watsonk,Watson,Kite
magnusa,Magnus,Acadoo
whendyw,Whendy,Whitt
robinc,Robin,Chuung
fenandof,Fenando,Foo
rickyz,Ricky,Zaumann
ingob,Ingo,Baldvin
barryz,Barry,Zaky

The objects stored in $users are then piped to the ForEach-Object cmdlet, where the current string object becomes accessible through the use of the special identifier, $_ (ForEach is an alias for the ForEach-Object cmdlet). With this technique, you no longer need to track your position with an index in order to enumerate the entire array. The desired elements in the string object are subsequently positioned at the respective parameters, such as $_.’Surname’ to -Lastname of the New-Mailbox cmdlet. The dot notation is a universal standard designed to access methods and properties in an object.

The New-Mailbox cmdlet expects a secure string to be supplied to the -Password parameter and that’s where the ConvertTo-SecureString cmdlet comes into play. In an enterprise environment, most IT administrators commonly assign standard passwords to new accounts and enable the “User must change password at next logon” option. You may have guessed by now that this is achieved using the -ResetPasswordOnNextLogon parameter to the New-Mailbox cmdlet. As a best practice, new accounts created this way are usually disabled until they are released to the user.

Unfortunately, I cannot find any option, cmdlet, object method or property to disable a user account that matches the “Account is disabled” setting in AD.

The rest of the script is fairly self-explanatory and that is another clear advantage of using PowerShell compared to classic favorites such as VBScript.

You can confirm that the users are created in the particular AD organizational unit (OU) by using the following construct:

[PS] C:\>Get-User -OrganizationalUnit ITAdmin | `
Format-Table name, firstname, lastname, recipienttype

Name     FirstName LastName RecipientType
----     --------- -------- -------------
magnusa  Magnus    Acadoo   UserMailbox
whendyw  Whendy    Whitt    UserMailbox
robinc   Robin     Chuung   UserMailbox
fenandof Fenando   Foo      UserMailbox
rickyz   Ricky     Zaumann  UserMailbox
ingob    Ingo      Baldvin  UserMailbox
barryz   Barry     Zaky     UserMailbox
dankyd   Danky     Daniels  UserMailbox
sweenyc  Sweeny    Conssiti UserMailbox
watsonk  Watson    Kite     UserMailbox

Sorry, No GUI for You
Falling back to the EMS is inescapable when you have to work on tasks that have limited or no equivalent options in the EMC. A few notable absences in EMC functionality include:

  • * -OutlookProvider
  • * -ExchangeCertificate
  • Public folder management (*-PublicFolder*)
  • Administration of Active Directory (*-ADPermission)
  • Mailbox permissions (*-MailboxPermission)

Even the closest official reference -- this discussion on the Microsoft Exchange Team blog -- does not go into the exact details of what’s possible or not with the graphical interface. David Elfassy, an MCT and Exchange expert, provides an unofficial list on his blog at http://elfassy.spaces.live.com/. It's a heavily discussed topic in the community -- see “Tasks that CANNOT be performed from the Exchange Management Console.” Official Microsoft sources suggest that there is no plan for such a list either for the upcoming Service Pack 1 for Exchange 2007, although a number of EMS-only features will now find life in the Exchange Management Console (e.g. public folder administration, availability management, etc.).

Why is this so important? As Exchange administrators begin the transition over to Exchange 2007, the challenge does not lie only with having to learn the new EMC to execute old familiar tasks, but also EMS to address the shortcomings of the EMC.

It’s been said that EMS is equivalent to raw mode in Exchange 5.5. Once you get up to speed with the shell, messaging tasks with EMS will be much faster, effective and efficient, and productivity levels will climb with the deployment of tried and tested, ready-made scripts that are guaranteed to be error-free.

As if this is not enough motivation for you, Exam 70-236 TS: Exchange Server 2007 Configuration contains an amazingly high percentage of questions touching on EMS. You are expected to know many of the cmdlets and their parameters inside-out, so as to correctly configure the settings as required by the test scenarios. Furthermore, you have to learn the exceptions on cmdlets with plural nouns and reinforce that learning by real-world EMS working experiences in order to tackle such questions comfortably.

References and Resources

Microsoft's site has many useful resources on Exchange, PowerShell and the Exchange Management Shell at the following links:

Also, check out these links at Microsoft TechNet:

I also recommend the SAPIEN Technologies blog for scripting and PowerShell information. -- DL

Get-Mailbox | ForEach { $_.WhenChanged }
With more and more enterprise Microsoft products adopting PowerShell as their principal administration and management framework, there is no better time than now to take a hard look at Exchange 2007’s implementation of PowerShell. Having a fundamental grasp of this core technology will dramatically change the way you approach scripting, elevating you to a secure and strategic foothold and assured of a bright PowerShell future.

Featured