This article explains the use of the Exchange Scripting Agent cmdlet extension, which allows you to execute additional PowerShell code when a cmdlet is executed. The Exchange cmdlet extension is controlled by a scripting agent configuration file and a organizational setting to enable/disable the scripting agent.

A scripting agent configuration file sample (ScriptingAgentConfig.xml.sample) is located in


The sample needs to be renamed to ScriptingAgentConfig.xml, to be picked up the PowerShell engine.

As always, a slight reminder: Test any modification in a test environment first, before you use the extension in a production environment.

After succesfull testing and deployment, you need to enable the scripting agent using

Enable-CmdletExtensionAgent "Scripting Agent"


Even thought that you can extend mostly any Exchange cmdlet, this example covers the extension of the New-Mailbox and Enable-Mailbox cmdlets in a multi domain and multi AD site environment.
This extension disables the following CAS mailbox settings, after a new mailbox has been created:

  • ActiveSync
  • IMAP4
  • POP3
  • MAPI over HTTP
What does the example do?
  • Extension is named MailboxProvisioning and handles the cmdlets New-Mailbox and Enable-Mailbox
  • Is called on trigger OnComplete
    • The extension code is called after the original cmdlet has finished
  • Code is executed, if the original cmdlet was successfully finished
  • Code is executed, if the mailbox created is not an archive
  • A slight delay of 10 seconds ensures that domain controller activities have been finished
    • Can be adjusted or even removed, depending on your environment
  • Try to fetch at least on of three user parameters to identify the user mailbox
    • Checking for Identity, Name, Alias
  • Fetch a list of all domain controllers in the current AD site where the Exchange server is located
  • Iterate through the list of domain controllers and try to fetch the new CAS mailbox
    • If fetched, remember the domain controller's FQDN
  • Change the CAS mailbox settings as needed and use the remembered domain controller as DC to write to

<?xml version="1.0" encoding="utf-8" ?>

  <Configuration version="1.0">

<Feature Name="MailboxProvisioning" Cmdlets="New-Mailbox,Enable-Mailbox">

<ApiCall Name="OnComplete">

If ($succeeded) {

if (!($provisioningHandler.UserSpecifiedParameters.Archive -eq $true)) {

# delay execution for 10 seconds, adjust as needed

Start-Sleep -s 10

# validate parameters to use a not null parameter

if ($provisioningHandler.UserSpecifiedParameters["Identity"] -ne $null) {

$user = $provisioningHandler.UserSpecifiedParameters["Identity"].ToString()


elseif ($provisioningHandler.UserSpecifiedParameters["Name"] -ne $null) {

$user = $provisioningHandler.UserSpecifiedParameters["Name"].ToString()


else {

$user = $provisioningHandler.UserSpecifiedParameters["Alias"].ToString()


# view entire forest in a multi domain environment

Set-AdServerSettings -ViewEntireForest:$true

# fetch domain controllers in AD site}

$server = Get-ExchangeServer $env:computername

$DCs = Get-DomainController | ?{$_.adsite -eq $}

$CasMailbox = $null

foreach($d in $DCs) {

while($CasMailbox -eq $null) {

# find a valid domain controller having the updated user object

$CasMailbox = Get-CASMailbox $user -DomainController $d.dnshostname -ErrorAction SilentlyContinue

# fetch DCs FQDN

$WriteDC = $d.DnsHostName




try {

# set CAS features as needed

Set-CasMailbox $user -ActiveSyncEnabled:$false -ImapEnabled:$false -PopEnabled:$false -MapiHttpEnabled:$false -DomainController $WriteDC -ErrorAction SilentlyContinue


catch {}







After adding the PowerShell code to the ScriptingAgentConfig.xml file, the file needs to be distributed across all Exchange servers. For distribution of the scripting agent configuration file I personally recommend Paul Cunningham's PowerShell script.

Be aware of the fact, that the scripting agent Xml is being validated using a strict schema validation. The scripting agent Xml is case sensitive.