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.