Share via


Use PowerShell Cmdlet Extensions to customize Exchange cmdlet behaviour

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

$exinstall\Bin\CmdletExtensionAgents

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"

Example

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 $server.site}

$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

break

}

}

try {

# set CAS features as needed

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

}

catch {}

}

}

</ApiCall>

</Feature>

</Configuration>

Notes

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.