Cmdlet Extension Agents (Part 1)

by [Published on 27 June 2013 / Last Updated on 1 Aug. 2013]

In this three-part article, the author will talk about and demonstrate how to use Cmdlet Extension Agents in Exchange 2013 to extend the functionality of any cmdlet. Specifically, we will see how to improve the mailbox provisioning process by automatically configuring mailbox features and settings such as archiving, ActiveSync, IMAP, Single Item Recovery and automatically send a welcome e-mail to new users.

If you would like to read the other parts in this article series please go to:

Introduction

Cmdlet Extension Agents are Exchange components that are invoked by cmdlets when the cmdlets run. These agents are available on any server role and, as the name suggests, they extend the capabilities of cmdlets that invoke them by assisting in processing data or performing additional actions based on the requirements of the cmdlet. They can be used to modify, replace or extend functionality of any Exchange cmdlet. For example, they can override a value provided by a user, perform actions outside of the cmdlet workflow, provide a value for a required parameter that was not provided, etc.

An example of such functionality is when creating a new mailbox. If an administrator does not specify a mailbox database when creating a new mailbox with Exchange 2007, the process fails. However, in Exchange 2010 and 2013, the New-Mailbox cmdlet invokes the Mailbox Resources Management agent whenever it is run. If a database is not specified, this agent automatically determines a suitable database on which to create the new mailbox and inserts that value into the Database parameter.

Note that cmdlet extension agents can only be invoked by Exchange 2010 and 2013 cmdlets as they are a feature introduced in Exchange 2010. Scripts cannot invoke these agents directly but if they contain Exchange 2010/2013 cmdlets, those cmdlets continue to call the cmdlet extension agents.

Unfortunately, cmdlet extension agents are not a well-known feature and, therefore, are often overlooked or ignored. A good example is the requirement that many organizations have to customize things immediately after creating a mailbox. They often develop custom scripts or even buy 3rd-party applications to achieve this, when cmdlet extension agents can very well be used to achieve most, if not all, these requirements.

In this article series we will use a particular cmdlet extension agent, called Scripting agent, in order to customize the mailbox provisioning process. Specifically, when a new mailbox is created we will automatically configure it for archiving, its permissions, enable Single Item Recovery, disable ActiveSync, configure other user attributes such as country and city, and send a welcome e-mail to the user.

Exchange 2013 Cmdlet Extension Agents

Exchange 2013 comes with 8 agents that can be invoked when a cmdlet runs. The picture below lists these agents, their priority and whether they are enabled by default or not:

Image
Figure 1.1:
Exchange 2013 Cmdlet Extension Agents

Although you cannot add or remove agents, you can use the Scripting Agent to run PowerShell scripts to extend the functionality of the cmdlets that use it. This is what this article series will focus on.

Most agents can be enabled or disabled, or you can change their priority if you want to replace the functionality of a specific agent with functionality you provide in a custom script that you call using the Scripting agent. The Admin Audit Log agent is the only one that cannot be disabled and, therefore, is considered a system agent.

Agents’ configuration is stored at the organization level. When an agent is enabled, disabled, or has its priority updated, this configuration change is set across every server in the organization. The exception is when adding script code to the Scripting agent as we will see in the second part of this article. In this case, you must update each server individually.

Agent Priority

The priority of an agent determines the order in which that agent is invoked while a cmdlet runs: an agent that has a higher priority is invoked first. Agents are ordered by their priority, from zero to the maximum number of agents. The closer to zero an agent’s priority is, the higher the priority of the agent.

This is important when two or more agents attempt to set the value of the same property. In this scenario, the agent with the highest priority sets the property value and all subsequent attempts to set the same property by lower priority agents are ignored.

As you can see from Figure 1, the Scripting agent is one of the agents with the lowest priority, meaning it runs after every other agent with the exception of the Admin Audit Log agent. As such, if you want to use it to set the value of properties that might be set by agents with a higher priority, you have the following options:

  • Disable the agent that currently sets the property;
  • Set the Scripting agent to a priority higher than the existing agent you want to replace;
  • Ensure the script that runs under the Scripting agent respects the value provided by the other agents.

Important:
Enabling and disabling agents or changing their priority can cause unintended effects if you do not completely understand what each agent does and how they interact with Exchange cmdlets!

Note that most cmdlets only invoke one agent, the Admin Audit Log agent. As such, you might not need to disable or update the priority of agents to ensure the Scripting agent takes priority over the rest.

In this article we will only be adding functionality to certain cmdlets. As such we do not need to disable any agents or change their priority. However, here is how you would do this:

Note:
The Cmdlet Extension Agents management role allows administrators to enable, disable and set the priority of cmdlet extension agents in the organization:

Image
Figure 1.2:
Cmdlet Extension Agents Management Role

To change the priority of the Scripting agent to 1 we use the Set-CmdletExtensionAgent cmdlet with the Priority parameter. This results in the priority of other agents to be automatically updated:

Image
Figure 1.3:
Changing Cmdlet Extension Agents’ Priority

To disable an agent, we use the Disable-CmdletExtensionAgent cmdlet. In this example, we are disabling the Mailbox Resources Management agent:

Image
Figure 1.4:
Disabling Cmdlet Extension Agents

Scripting Agent

As mentioned before, we can use the Scripting agent cmdlet extension agent to insert our own scripting logic into the execution of Exchange cmdlets. Using the Scripting agent we can, for example, add conditions, override values and set up reporting.

Important:
When this agent is enabled, it is invoked every single time a cmdlet is run, including not only cmdlets run directly by administrators in the Exchange Management Shell but also operations performed in the Exchange Administration Center (EAC) (since these execute cmdlets in the background) and even cmdlets run by Exchange services. The only exception to this is when cmdlets with the Get verb are run. In this case, the Scripting agent is not invoked.

This is a great feature because it allows administrators to control the behaviour of cmdlets from one location no matter which tool or console that cmdlet is invoked from. As mentioned before, in this article we will look at customizing the mailbox creation process. By using the Scripting agent, it does not matter how a mailbox is created (using a script, a 3rd-party tool, the Shell, the EAC, etc.), the agent will always be invoked and the mailbox will be created according to our preferences.

When the Scripting agent is invoked, the cmdlet checks whether any scripts in the agent are configured to be invoked by the cmdlet. If a script should be run, the cmdlet tries to invoke any APIs defined in the script. The following APIs are available and are invoked in the following order:

  1. ProvisionDefaultProperties can be used to set values of properties on objects when they are created. When you set a value, that value is returned to the cmdlet and the cmdlet sets the value on the property. You can fill in values on properties if the user did not specify a value, or you can override the value specified by the user;
  2. UpdateAffectedIConfigurable can be used to set values of properties on objects after all other processing has been completed, but the Validate API has not yet been invoked;
  3. Validate can be used to validate the values on an object's properties that are about to be set by the cmdlet. This API is called just before a cmdlet writes any data. You can configure validation checks that allow a cmdlet to either succeed or fail. If a cmdlet passes the validation checks in this API, the cmdlet is allowed to write the data. If the cmdlet fails the validation checks, it returns any errors defined in this API;
  4. OnComplete is used after all cmdlet processing is complete. It can be used to perform post-processing tasks such as writing data to an external database.

In this article series we will focus mainly on the OnComplete API but I will also provide examples of what can be done using the Validate API.

Conclusion

In this first part of this article series, we had a look at what Cmdlet Extensions Agents are and how they work. The second and third parts will be full hands-on as we will see how to use the Scripting agent to extend any Exchange cmdlet and go through a few examples about improving the mailbox provisioning process.

If you would like to read the other parts in this article series please go to:

Featured Links