You are on page 1of 12

Did you know that the Identity parameter is a “positional parameter”?

That means you

can use:
Get-Mailbox “domain\user” instead of: Get-Mailbox -Identity “domain\user”
It’s a neat usability shortcut!

To return all scripts that are found in your path, type:

Get-Command -Type ExternalScript
And for a useful shortcut, assign it in your profile as:
Function Get-Scripts { Get-Command -Type ExternalScript }

Are you tired of typing a long command every time that you want to do something? Alias
it! Type:
Set-Alias GetSg Get-StorageGroup
For all the current aliases, type:

The Exchange Management Shell is a calculator too! Try it directly in the command line:
1.2343+3123 or (23/435)*2

Command line 911! Do you need help? Type:

Help or -?
You can also perform wildcard character searches and partial name matches:
Help *UM*
And you can get more details about a cmdlet by using:

A quick shortcut to get all the parameters for a cmdlet is:

Get-Command | Format-List Definition
or abbreviated:
Gcm | Fl Def*

The tilde character ( ~ ) should be familiar to Unix users. It represents the shortcut to
your root directory. To see what it’s evaluated to by default, type:
Dir ~
You can use it as a useful shortcut:
Cp SomeFile “~\My Documents”
Do you want to move mailboxes? Type:
You can move all users from server SRV1 to server SRV2 as follows:
Get-Mailbox -Server SRV1 | Move-Mailbox -TargetDatabase SRV2

CTRL+C is the equivalent of the hard-break command in the Exchange Management

Shell. If a command is taking too long to run or you want to cancel an operation quickly,
press CTRL+C to stop execution.

Pushd and Popd work the same way in the Exchange Management Shell as they do in
cmd.exe. Type:

XML over everything! The Exchange Management Shell treats XML as a native type, so
that you can do interesting things like:
$Sample = [XML](Get-Content SomeXMLFile.xml)
This command assigns $Sample to the actual XML object. To see it, type:
To navigate it, type:
No need for text parsing when you want to load XML data!

Cmdlets that end in “Config” manage singleton configuration, either one per server or
organization. For these tasks, you don’t have to specify an identity because there is only
one instance of the configuration. You may have to specify the Server parameter if the
configuration is per server.

To get a list of all users on an Exchange 2007 server who are not Unified Messaging-
enabled type, use:
Get-UmMailbox | ForEach { If($_.UmEnabled -Eq $False){$_.Name}}

To get a list of all users on an Exchange 2007 server who are Unified Messaging-enabled
type, use:
Get-UmMailbox | ForEach { If($_.UmEnabled -Eq $True){$_.Name}}

To display the user’s alias formatted in a table together with the user’s Exchange 2007
server name and telephone extension, type:
Get-UmMailbox | Format-Table ServerName,@{e={$_.SamAccountName};Label=”User
Alias”},@{Expression=”Extensions”;Label=”Telephone numbers”}

To display the list of UM IP gateway server names that are disabled for outbound calling
and hunt groups that are associated with a UM IP gateway server, use:
Get-UmIpGateway | ForEach {If($_.OutCallsAllowed -Eq $False){ “Gateway Name = ”
+$_.Name;ForEach ($HuntGroup In $_.Huntgroups){”Huntgroups ” + $Huntgroup}}}

If you want to test all IP Block List providers, you just have to pipe the Get-
IpBlockListProvider cmdlet to the Test-IpBlockListProvider cmdlet:
Get-IpBlockListProvider | Test-IpBlockListProvider -IpAddress

Before you remove an object by using the Remove verb, use the WhatIf parameter to
verify the results are what you expect.

Sometimes it’s useful to convert the output of a cmdlet to a string to interoperate with
native cmdlets. For example, type:
Get-Command | Out-String | Findstr “command”

Get all Win32 WMI information, such as perfmon counters and local computer
configurations. For example, type:
Get-WMIObject Win32_PerfRawData_PerfOS_Memory

Tired of spam? Who isn’t? You can configure real-time block list (RBL) providers with
the Exchange Management Shell by running the following two commands:
Set-IPBlockListProvidersConfig -Enabled $True -ExternalMailEnabled $True
and then
Add-IPBlockListProvider -Name -LookupDomain -AnyMatch $True

Access the event log from the Exchange Management Shell. To retrieve the whole event
log, run:
Get-EventLog Application | Format-List
To retrieve all Exchange-related events, run:
Get-EventLog Application | Where { $_.Source -Ilike “*Exchange*” }

One benefit of the Exchange Management Shell is that cmdlets can emit objects to the
console. You can then manipulate this output and organize it in interesting ways. For
example, to get a quick view in tabular format, use Format-Table:
Get-Mailbox | Format-Table Name,Database,RulesQuota

Did you forget a property name? Not a problem because you can use wildcard characters
to retrieve all properties that match the part of the name that you specify:
Get-Mailbox | Format-Table Name,*SMTP*

Do you want to work with data that is contained in a CSV file? Use Import-CSV to assign
the data to an object. For example, type:
$MyCSV = Import-CSV TestFile.CSV
You can then manipulate the data easily in the Exchange Management Shell. For
example, if there is a column called Mailboxes in the CSV data, you can use the
following commands to sort or group the data by the Mailboxes column:
To sort: $MyCSV | Sort Mailboxes
To group: $MyCSV | Group Mailboxes

This command spins through all your mailbox servers and reconnects all the uniquely
identified but disconnected mailboxes in any one of the mailbox stores:
Get-ExchangeServer | `
Where { $_.IsMailboxServer -Eq ‘$True’ } `
| ForEach { Get-MailboxStatistics -Server $_.Name `
| Where { $_.DisconnectDate -NotLike ” } `
| ForEach { Connect-Mailbox -Identity `
$_.DisplayName -Database $_.DatabaseName} }

Tab completion reduces the number of keystrokes that are required to complete a cmdlet.
Just press the TAB key to complete the cmdlet you are typing. Tab completion kicks in
whenever there is hyphen (-) in the input. For example:
should complete to Get-SendConnector. You can even use regular expressions, such as:
Pressing the TAB key when you enter this command cycles through all cmdlets that
match the expression, such as the Unified Messaging Mailbox policy cmdlets.

Do you want to create a group of test users in your lab? Use this command:
1..100 | ForEach { Net User “User$_” MyPassword=01 /ADD /Domain; Enable-Mailbox
“User$_” -Database }

Do you want to change the authentication settings on an Outlook Web Access virtual
directory? Try the following command as an example. It changes authentication from
forms-based authentication to Windows authentication:
Set-OwaVirtualDirectory -Identity “OWA (Default Web Site)” -FormsAuthentication 0
-WindowsAuthentication 1

Do you want to set the properties on all or some Outlook Web Access virtual directories?
Pipe the output of Get-OwaVirtualDirectory to the Set-OwaVirtualDirectory cmdlet. For
example, the following command sets the Gzip level for all Outlook Web Access virtual
Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -GzipLevel High

Do you want to remove an ActiveSync device from a user’s device list? Type:
This cmdlet can be helpful for troubleshooting devices that do not synchronize
successfully with the server.

Do you want to clear all data from a mobile device? Use:

Specify a time of day to clear the device, or let the task complete the next time that the
device connects to the server.

Do you want to see a list of all devices that synchronize with a user’s mailbox? Type:
A variety of information is returned including device name, operating system, and last
sync time.

Has one of your users asked you to recover their mobile device synchronization
password? To return the user’s password, type:
Get-ActiveSyncDeviceStatistics -ShowRecoveryPassword

Do you want to move the storage group path to another location? Type:
Move-StorageGroupPath -LogFolderPath DestLogFolder
To change only the path setting without moving data, use this command together with the
ConfigurationOnly parameter. This command is especially useful for disaster recovery.

Misuse of this cmdlet will cause data loss.
Do you want to move your database path to another location? Type:
Move-DatabasePath -EdbFilePath DestFileName
To change the file path setting without moving data, use this command together with the
ConfigurationOnly parameter. This command is especially useful for disaster recovery.

Misuse of this cmdlet will cause data loss.

To set the dial restrictions on a specific Unified Messaging dial plan, type:
$Dp = Get-UmDialPlan -Identity
$Dp.OutsideLineAccessCode = 9
$Dp | Set-UmDialPlan

Do you need an easy way to add a new primary SMTP address to a group of mailboxes?
The following command creates a new e-mail address policy that assigns the domain to the primary SMTP address of all mailboxes with Contoso in
the company field:
New-EmailAddressPolicy -Name Contoso -RecipientFilter {Company -Eq “Contoso”}
-EnabledPrimarySMTPAddressTemplate “”

Do you want to retrieve a group of objects that have similar identities? You can use
wildcard characters with the Identity parameter to match multiple objects. Type:
Get-Mailbox *John*
Get-ReceiveConnector *
Get-JournalRule *discovery*

Do you want to configure a group of objects that have similar identities? You can use a
wildcard characters with the Identity parameter when you use a Get cmdlet and pipe the
output to a Set cmdlet. Type:
Get-Mailbox *John* | Set-Mailbox -ProhibitSendQuota 100MB
This command matches all mailboxes with the name “John” in the mailbox’s identity and
set the ProhibitSendQuota parameter to 100MB.

Most cmdlets let you pass the output of one noun to another noun in order to view or
modify related objects. For example, you might want to set the mailbox limit on all
mailboxes that reside in a specific mailbox database on a server. You can do this by using
this command:
Get-MailboxDatabase “Executives” | Get-Mailbox | Set-Mailbox -ProhibitSendQuota
This command retrieves all the mailboxes that reside in the “Executives” mailbox
database and sets their ProhibitSendQuota value to 300MB.

Forgot what the available parameters are on a cmdlet? Just use tab completion! Type:
Set-Mailbox -
When you type a hyphen ( - ) and then press the Tab key, you will cycle through all the
available parameters on the cmdlet. Want to narrow your search? Type part of the
parameter’s name and then press the Tab key. Type:
Set-Mailbox -Prohibit

Say goodbye to ping. Say hello to Test-MapiConnectivity! Use Test-MapiConnectivity to

troubleshoot connectivity problems between your users and your servers. Combine Test-
MapiConnectivity with a variety of cmdlets to target your specific issue without having to
manually dig for the information:
Mailboxes: Get-Mailbox | Test-MapiConnectivity
Mailbox databases: Get-MailboxDatabase | Test-MapiConnectivity
Servers: Get-MailboxServer | Test-MapiConnectivity

Do you want to add an alias to multiple distribution groups that have a similar name?
Get-DistributionGroup *Exchange* | Add-DistributionGroupMember -Member kim
This command adds the alias “kim” to all distribution groups that contain the word

Do you want to record exactly what happens when you’re using the Exchange
Management Shell? Use the Start-Transcript cmdlet. Anything that you do after you run
this cmdlet will be recorded to a text file that you specify. To stop recording your session,
use the Stop-Transcript cmdlet.
Notice that the Start-Transcript cmdlet overwrites the destination text file by default. If
you want to append your session to an existing file, use the Append parameter:
Start-Transcript c:\MySession.txt -Append

Here’s a handy tip for repeating a command a given number of times. Instead of writing a
For loop, use the following syntax:
1..10 | ForEach { “do something here” }
For example, the following command creates 10 new storage groups that have the names
sg1 through sg10 on the server TestServer:
1..10 | ForEach { New-StorageGroup -Name “sg$_” -server TestServer }
Do you want to know when your mailbox databases were backed up last? Type:
Get-ExchangeServer | Get-MailboxDatabase -Status | Format-Table Name, *Back*

Do you want to move all the mailboxes from one mailbox database to another? You can
do this easily by using the following command:
Get-MailboxDatabase | Get-Mailbox | Move-Mailbox -TargetDatabase
You can even use wildcard characters with the Get-MailboxDatabase cmdlet to
consolidate mailboxes from multiple source mailbox databases into a single destination
mailbox database.

Do you have a user who has network access but maintains an external mail account
outside your Exchange organization? With Exchange Server 2007, you can now create
mail-enabled users that are regular Active Directory accounts, but also behave like mail-
enabled contacts. By using the Enable-MailUser cmdlet, you can add e-mail contact
attributes to any existing Active Directory user who does not already have a mailbox on
an Exchange server. Users in your Exchange organization will then be able to send e-mail
messages to that user’s external mail account. Type:
Enable-MailUser -Identity -ExternalEmailAddress

Do you want to change the default prohibit send quota for a mailbox database? Type:
Set-MailboxDatabase -ProhibitSendQuota
You can specify a bytes qualifier when you use the ProhibitSendQuota parameter. For
example, if you want to set the prohibit send quota to 200 megabytes, type:
ProhibitSendQuota 200MB
You can also configure the IssueWarningQuota parameter and the
ProhibitSendReceiveQuota parameter in the same way.

Do you want to know what version of Exchange Server each of your servers is running?
Get-ExchangeServer | Format-Table Name, *Version*

Do you want to know which Exchange 2007 servers have not yet been configured with a
valid product key and whether their trial period has expired? Type:
Get-ExchangeServer | Where { $_.IsExchange12TrialEdition -Eq $true } | Format-Table
Name, *Trial*

Do you want to determine whether a server is running Exchange Server 2007 Standard
Edition or Exchange Server 2007 Enterprise Edition? Type:
Get-ExchangeServer | Format-Table Name, Edition
If you want to view which edition all your Exchange servers are running, omit the

Do you want to create a new resource mailbox that can be used to book a meeting room?
New-Mailbox -Name -UserPrincipalName -Database -OrganizationalUnit -Room
This command creates a disabled Active Directory user who has a mailbox that accepts
meeting requests from users.

Do you want to add a disclaimer to all outbound e-mail messages? Type:

$Condition = Get-TransportRulePredicate FromScope
$Condition.Scope = “InOrganization”
$Condition2 = Get-TransportRulePredicate SentToScope
$Condition2.Scope = “NotInOrganization”
$Action = Get-TransportRuleAction ApplyDisclaimer
$Action.Text = “Sample disclaimer text”
New-TransportRule -Name “Sample disclaimer” -Condition @($Condition, $Condition2)
-Action @($Action)

Do you want to control the properties of e-mail messages sent to a specific domain? Use
the RemoteDomain cmdlets. Create a new remote domain by using the New-
RemoteDomain cmdlet. Type:
New-RemoteDomain -Name “ Configuration” -DomainName
Then modify the properties that you want for this remote domain by using the Set-
RemoteDomain cmdlet:
Set-RemoteDomain “ Configuration” -AutoReplyEnabled $True
-AutoForwardEnabled $True

You can control which features are available to Outlook Web Access users by using the
Set-OwaVirtualDirectory cmdlet. Type:
Set-OwaVirtualDirectory “OWA (Default Web Site)” -ContactsEnabled $True
-ChangePasswordEnabled $True

Booleans are parameters that can be evaluated as either $True or $False. Booleans are
typically used as a flag on an object that modifies the behavior of that object. In the
Exchange Management Shell, you must supply a Boolean parameter with either a $True,
$False, 1, or 0. No other values are accepted, including True or False. For example, the
following commands both set the ExternalDsnSendHtml parameter to $True:
Set-TransportServer -ExternalDsnSendHtml $True
Set-TransportServer -ExternalDsnSendHtml 1
Do you want to remove all e-mail messages that were sent from a certain domain name
from a server’s queues without generating a non-delivery report (NDR)? Type:
Remove-Message -WithNDR $False -Filter { FromAddress -Like “*” }

Do you want an easy way to apply deleted item retention limits across multiple databases
and servers? Try the following command to configure deleted item retention across all
databases on a specified server:
Get-MailboxDatabase -Server | Set-MailboxDatabase -ItemRetention 45.00:00:00
You can also apply the same deleted item retention limits or mailbox retention limits
across all servers in your organization:
Get-MailboxDatabase | Set-MailboxDatabase -ItemRetention 45.00:00:00
-MailboxRetention 120.00:00:00

Do you want to know what permissions an Active Directory user account has on a
specific mailbox? Use:
Get-Mailbox | Get-MailboxPermission -User

Do you want to know which mailboxes a specific Active Directory user has permissions
to? Type:
Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission -User | Format-Table
Identity, AccessRights, Deny
Caution: This command enumerates all the mailboxes in your organization. If you have
lots of mailboxes, you may want to target specific mailboxes.

Do you want to get a list of the backup status of all mailbox databases in your
organization? Type:
Get-MailboxDatabase -Status | Format-Table Name, Server, *Backup*
How about just the mailboxes on a specific server? Type:
Get-MailboxDatabase -Server -Status | Format-Table Name, *Backup*

To retrieve the current status of an Exchange server or database, use the Status parameter.
For example:
Get-ExchangeServer -Status | Format-List
Get-MailboxDatabase -Server -Status | Format-List

Do you want to view the mounted status of all mailbox databases? Type:
Get-MailboxDatabase -Status | Format-Table Name, Server, Mounted
What’s the difference between server-side filtering and client-side filtering? Server-side
filtering is used with the recipient and queue cmdlets, which support the Filter parameter,
because these cmdlets can return large result sets. The server filters the results by using
the criteria you specify, and then sends you the filtered results. Client-side filtering can be
used with any cmdlet. The entire result set is sent to the client computer, which then
filters the data and provides a filtered result set. Client-side filtering uses the Where-
Object cmdlet, which can be shortened to Where.

With Exchange Server 2007 Unified Messaging (UM), you can redirect unauthenticated
callers to certain telephone extensions to an operator instead of to the extension that was
dialed. To list users for whom UM transfers unauthenticated callers to the operator,
instead of to the user, type:
Get-UMMailbox | `
Where-Object { $_.AllowUMCallsFromNonUsers -eq `
“None” }

You can use client-side filtering to return only the data that you want to see or work with.
The following example retrieves all Active Directory user accounts that are in the
Engineering department and puts the results in a table with two columns, Name and
Department. By using the ResultSize parameter, the Get-User cmdlet limits the result set
to 2,000 users.
Get-User -ResultSize 2000 | Where { $_.Department -Eq “Engineering” } | Format-Table
Name, Department

The special variable $_ represents the objects being passed from one cmdlet to another
cmdlet in the pipeline. The $_ variable is automatically initiated by the shell and is bound
to the current pipeline object. You can access the properties of the object assigned to the
$_ variable as you would any other object. The following example shows how you can
view the Name property of each mailbox object that is passed through the pipeline:
Get-Mailbox | ForEach { $_.Name }

You can import CSV files and treat them as objects by using the Import-Csv cmdlet. Each
row in a CSV file becomes an element in an array, and each column becomes a property.
You can assign the CSV file to a variable or you can pipe its contents directly to another
cmdlet. In the following example, there are three columns in the CSV file, Name, Alias
and EmailAddress, with several rows that the ForEach cmdlet will cycle through. The
data in each row is used to create a new mail contact.
Import-Csv | ForEach { New-MailContact -Name $_.Name -Alias $_.Alias
-ExternalEmailAddress $_.EmailAddress -OrganizationalUnit Users }
Do you want to customize your Exchange Management Shell profile? Run the following
command to determine the location of your Microsoft.PowerShell_profile.ps1 file is:
You may have to create the PSConfiguration folder and
Microsoft.PowerShell_profile.ps1 file. After you’ve done that, you can add your favorite
functions and aliases, which will be loaded every time that the Exchange Management
Shell is opened.

Use the following commands to configure a managed folder policy that will enforce a
maximum personal e-mail folder size of 10MB on all the mailboxes in your organization.
New-ManagedFolder -Name “Reference e-mail folder with 10mb quota” -FolderName
“Personal and Reference E-mail” –StorageQuota 10MB
New-ManagedFolderMailboxPolicy “Personal Folder Policy” -ManagedFolderLinks
“Reference e-mail folder with 10mb quota”
Get-Mailbox -ResultSize Unlimited | Set-Mailbox -ManagedFolderMailboxPolicy
“Personal Folder Policy”
Set-MailboxServer -ManagedFolderAssistantSchedule “Sun.12:00-Sun.11:00″

Do you want to see everything that occurs when you run a command? Include the
Verbose parameter with the command. This parameter instructs the Exchange
Management Shell to display detailed information about each action that the server takes
to complete the command. This information can be useful in troubleshooting.

Any cmdlet that accepts a size value lets you specify whether the integer value is in
kilobytes (KB), megabytes (MB), gigabytes (GB), or terabytes (TB). For example:
Set-Mailbox “Kim Akers” -ProhibitSendQuota 200MB

The Exchange Management Shell can log all the Exchange-related commands that
modify objects in some way. Exchange-related command activity is logged to the
PowerShell event log. To enable Exchange-related command logging, run the following
Management.PowerShell.Admin -Name LogpipelineExecutionDetails -value 1