Automating Tasks With Scripting Agent Cmdlet Extension Agent In Exchange

MS Exchange

Cmdlet extension agents are new components in Exchange 2010 that are called by Exchange 2010 cmdlets, when they are run. It is used to extend the functionality of Exchange 2010 cmdlets by running a script or set of code after the Exchange cmdlet has run. For example, you can run a set of configurations after a new mailbox has been created, basically calling the scripting agent to run a code after the New-Mailbox cmdlet completes. Scripting agent is one of the seven cmdlet extension agents available in Exchange 2010 and is the one that is disabled by default.

Get-CmdletExtensionAgent will list all the seven agents. Run Get-CmdletExtensionAgent | ft name, priority, enabled โ€“wrap โ€“autosize to get a refined output.

Get all cmdletextensionagents

I looked at the scripting agent as one of my client asked me ways to automate things to a certain extend. I will explain the process of using the scripting agent based on what I had been asked. My client wanted to make sure that all newly created mailboxes had the following configurations, without manually setting each.

  • POP, IMAP, ActiveSync is disabled
  • Outlook Anywhere is disabled
  • Single Item Recovery is enabled
  • Fields like Country, City, Street Address, Company in the user properties needs to be filled in automatically.
  • Block users from using Outlook in online mode
  • Set the company OWA Mailbox Policy

Scripting agent can be used to do what my client wanted and I set it up for them. The scripting agent, when enabled, looks for a file named โ€œScriptingAgentConfig.xmlโ€ within the BinCmdletExtensionAgents. By default, a โ€œScriptingAgentConfig.xml.sampleโ€ file exists in the same location which gives an idea of the code that needs to go in the xml file. Open the sample file using notepad and understand the basic syntax the xml file needs.

Sample scripting agent config

Below is the basic syntax you need for the config xml file, irrespective of what you are trying to achieve.

if($succeeded)
{ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  PowerShell cmdletsย ย ย ย ย ย ย ย ย ย ย  }


Below is the code that I used to achieve what my client wanted.

ย ย ย ย ย ย ย ย ย ย  if($succeeded)
{

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  $mailbox = $provisioningHandler.UserSpecifiedParameters[“Alias”]

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Set-CASMailbox $mailbox -ImapEnabled $false -POPEnabled $false โ€“ActiveSyncEnabled $false โ€“OWAMailboxPolicy “HEW OWA Policyโ€ โ€“MAPIBlockOutlookRpcHTTP $true โ€“MAPIBlockOutlookNonCachedMode $true

ย ย ย ย ย ย ย ย  Set-User -City ‘London’ -CountryOrRegion ‘United Kingdom’ย  -Company ‘How Exchangeย  Works’ -Identity $mailbox

ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย  Set-Mailbox $mailbox -SingleItemRecoveryEnabled $true
}

ย The line explains that we want our code to run whenever a new-mailbox or enable-mailbox cmdlet runs successfully. Once one of the cmdlets (new-mailbox or enable-mailbox) runs successfully either via Shell, Console or custom applications, we are instructing the scripting agent to run a set of PowerShell cmdlets which all Exchange admins are familiar with. In our case, the cmdlets needed to run are Set-CASMailbox, Set-User and Set-Mailbox. We are storing the alias of the user to a variable ($mailbox) in our case to re-use in the commands below.

I copied the entire code below to notepad and saved it as ScriptingAgentConfig.xml inside BinCmdletExtensionAgents folder.

scripting agent config

Next step is to enable the scripting agent. The agent should only be enabled once the ScriptingAgentConfig.xml is in place. Otherwise, all Exchange cmdlets except the โ€œGet-nounโ€ will throw errors. Run Enable-CmdletExtensionAgent โ€œScripting Agentโ€ to enable the agent.

Enable scripting agent

Time to test! I created a test mailbox and the scripting agent configured all the options my client wanted.

Test Mailbox

Confirmation of working scripting agent

Now that you understand the power of scripting agent, you can automate tasks to make your life easier Winking smile

Other Popular Articles


MS Exchange

Scripting Agent Initialization Failed: “File is not found” Error During Exchange 2016 Setup

MS Exchange

EAC Access While Co-Existing Exchange 2013 With 2010

MS Exchange

Delete All Calendar Entries In An Exchange 2010 Mailbox

29 thoughts on “Automating Tasks With Scripting Agent Cmdlet Extension Agent In Exchange”

  1. Replace “Name” in your script by “Alias” this way it will work. When creating a new mailbox with a new user -name is used, but with an existing user (command is enable-mailbox) -name is not used, but -identity. -alias is used in both options, so it’s better to use that instead.

    Reply
  2. Hi Rajith,
    Great article but I had an issue when creating a new mailbox account.
    I have only one command in ScriptingAgentConfig.xml file which set a retention policy. The command looks like this:

    Set-Mailbox -Identity $Name -RetentionPolicy $retpolicy

    and it is called in the section when condition If($succeeded) is true.

    Very often when creating a new mailbox account from the PowerShell I got the warning that the account has not been found on my AD server. It says: “The operation couldn’t be performed because object ‘[user_name]’ couldn’t be found on ‘ad.mydomain.com’.

    I can see that the account is created in AD but the retention policy is not applied.
    Is it a know bug (I got Exch 2010 SP2 RU6) or can I do something so it will not happen again?

    Mike

    Reply
  3. it took out the first part, reposting:
    ————————————————————–

    if($succeeded) {
    start-sleep -s 10
    $newmailbox = $provisioningHandler.UserSpecifiedParameters[“Name”]
    Get-mailbox $newmailbox | ForEach-Object {Set-MailboxFolderPermission $_”:\Calendar” -User default -AccessRights Reviewer}
    }

    ————————————————————–

    Reply
  4. <Hello Rajith

    I followed your steps but encontered the following issue once I tried to Enable a mailbox of and existing user using EMS or EMC,

    When I use New-Mailbox cmdlet I donโ€™t have any issue, the warning is just with the โ€œEnable-Mailboxโ€ cmdlet

    This is my code .xml code:

    if($succeeded) {
    $newmailbox = $provisioningHandler.UserSpecifiedParameters[“Name”]
    set-casmailbox $newmailbox -popenabled:$false -imapenabled:$false -activesyncenabled:$false
    }

    this is my warning:

    WARNING: The cmdlet extension agent with the index 5 has thrown an exception in OnComplete(). The exception is:
    Microsoft.Exchange.Provisioning.ProvisioningException: ScriptingAgent: Exception thrown while invoking scriptlet for
    OnComplete API: Cannot bind argument to parameter โ€˜Identityโ€™ because it is null.. โ€”>
    System.Management.Automation.ParameterBindingValidationException: Cannot bind argument to parameter โ€˜Identityโ€™ because
    it is null.
    at System.Management.Automation.ParameterBinderBase.ValidateNullOrEmptyArgument(CommandParameterInternal parameter,
    CompiledCommandParameter parameterMetadata, Type argumentType, Object parameterValue, Boolean recurseIntoCollections)
    at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter,
    CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
    at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument,
    MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
    at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets,
    CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
    at System.Management.Automation.ParameterBinderController.BindPositionalParametersInSet(UInt32 validParameterSets,
    Dictionary`2 nextPositionalParameters, CommandParameterInternal argument, ParameterBindingFlags flags,
    ParameterBindingException& bindingException)
    at System.Management.Automation.ParameterBinderController.BindPositionalParameters(Collection`1 unboundArguments,
    UInt32 validParameterSets, UInt32 defaultParameterSet, Boolean ignoreArgumentsThatLookLikeParameters,
    ParameterBindingException& outgoingBindingException)
    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1
    arguments)
    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
    at System.Management.Automation.CommandProcessor.BindCommandLineParameters(CommandParameterInternal[] parameters)
    at System.Management.Automation.CommandProcessor.Prepare(CommandParameterInternal[] parameters)
    at System.Management.Automation.CommandProcessorBase.DoPrepare(CommandParameterInternal[] parameters)
    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable
    errorResults, Boolean enumerate)
    โ€” End of inner exception stack trace โ€”
    at Microsoft.Exchange.ProvisioningAgent.ScriptingAgentHandler.OnComplete(Boolean succeeded, Exception e)
    at Microsoft.Exchange.Provisioning.ProvisioningLayer.OnComplete(Task task, Boolean succeeded, Exception exception)

    Thanks a lot!!

    Reply
    • this is mine and it works. this sets user’s default user on the calendar to reviewer. So everyone in the company can review that user’s calendar.

      anyone know how to add a domain controller to the script so that the exchange server queries a specific DC where the object was created?

      Took 3 months to find:

      if($succeeded) {
      start-sleep -s 10
      $newmailbox = $provisioningHandler.UserSpecifiedParameters[“Name”]
      Get-mailbox $newmailbox | ForEach-Object {Set-MailboxFolderPermission $_”:\Calendar” -User default -AccessRights Reviewer}
      }

      Reply
  5. Hello Rajith

    I followed your steps but encontered the following issue once I tried to Enable a mailbox of and existing user using EMS or EMC,

    When I use New-Mailbox cmdlet I don’t have any issue, the warning is just with the “Enable-Mailbox” cmdlet

    This is my code .xml code:

    if($succeeded) {
    $newmailbox = $provisioningHandler.UserSpecifiedParameters[“Name”]
    set-casmailbox $newmailbox -popenabled:$false -imapenabled:$false -activesyncenabled:$false
    }

    this is my warning:

    WARNING: The cmdlet extension agent with the index 5 has thrown an exception in OnComplete(). The exception is:
    Microsoft.Exchange.Provisioning.ProvisioningException: ScriptingAgent: Exception thrown while invoking scriptlet for
    OnComplete API: Cannot bind argument to parameter ‘Identity’ because it is null.. —>
    System.Management.Automation.ParameterBindingValidationException: Cannot bind argument to parameter ‘Identity’ because
    it is null.
    at System.Management.Automation.ParameterBinderBase.ValidateNullOrEmptyArgument(CommandParameterInternal parameter,
    CompiledCommandParameter parameterMetadata, Type argumentType, Object parameterValue, Boolean recurseIntoCollections)
    at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter,
    CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
    at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument,
    MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
    at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets,
    CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
    at System.Management.Automation.ParameterBinderController.BindPositionalParametersInSet(UInt32 validParameterSets,
    Dictionary`2 nextPositionalParameters, CommandParameterInternal argument, ParameterBindingFlags flags,
    ParameterBindingException& bindingException)
    at System.Management.Automation.ParameterBinderController.BindPositionalParameters(Collection`1 unboundArguments,
    UInt32 validParameterSets, UInt32 defaultParameterSet, Boolean ignoreArgumentsThatLookLikeParameters,
    ParameterBindingException& outgoingBindingException)
    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1
    arguments)
    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
    at System.Management.Automation.CommandProcessor.BindCommandLineParameters(CommandParameterInternal[] parameters)
    at System.Management.Automation.CommandProcessor.Prepare(CommandParameterInternal[] parameters)
    at System.Management.Automation.CommandProcessorBase.DoPrepare(CommandParameterInternal[] parameters)
    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable
    errorResults, Boolean enumerate)
    — End of inner exception stack trace —
    at Microsoft.Exchange.ProvisioningAgent.ScriptingAgentHandler.OnComplete(Boolean succeeded, Exception e)
    at Microsoft.Exchange.Provisioning.ProvisioningLayer.OnComplete(Task task, Boolean succeeded, Exception exception)

    Thanks a lot!!

    Reply
  6. Hi,

    I have tried to set calendar permissions to Reviewer default on new mailboxes, but I keep getting an error.
    The script is:

    if($succeeded) {
    $newmailbox= $provisioningHandler.UserSpecifiedParameters[“Name”]
    Add-MailBoxFolderPermission -Identity $newmailbox”:\Calendar” -User Default -AccessRights Reviewer
    }

    But I receive this error:
    Warning:
    The cmdlet extension agent with the index 5 has thrown an exception in OnComplete(). The exception is: Microsoft.Exchange.Provisioning.ProvisioningException: ScriptingAgent: Exception thrown while invoking scriptlet for OnComplete API: An undefined executing user property is being used. Property Name :’executingUserid’.. —> Microsoft.Exchange.Configuration.Authorization.ExecutingUserPropertyNotFoundException: An undefined executing user property is being used. Property Name :’executingUserid’.
    at Microsoft.Exchange.Management.StoreTasks.SetTenantXsoObjectWithFolderIdentityTaskBase`1.PrepareMailboxUser()
    at Microsoft.Exchange.Management.StoreTasks.SetMailboxFolderPermissionBase.CreateSession()
    at Microsoft.Exchange.Configuration.Tasks.DataAccessTask`1.InternalStateReset()
    at Microsoft.Exchange.Configuration.Tasks.SetObjectTaskBase`2.InternalStateReset()
    at Microsoft.Exchange.Configuration.Tasks.SetTenantADTaskBase`3.InternalStateReset()
    at Microsoft.Exchange.Management.StoreTasks.SetTenantXsoObjectWithFolderIdentityTaskBase`1.InternalStateReset()
    at Microsoft.Exchange.Configuration.Tasks.Task.ProcessRecord()
    at System.Management.Automation.CommandProcessor.ProcessRecord()
    — End of inner exception stack trace —
    at Microsoft.Exchange.ProvisioningAgent.ScriptingAgentHandler.OnComplete(Boolean succeeded, Exception e)
    at Microsoft.Exchange.Provisioning.ProvisioningLayer.OnComplete(Task task, Boolean succeeded, Exception exception)

    Reply
  7. Rajith,

    Do I need to enable the scripting agent and copy the .xml file to ALL my Exchange servers, or just my MBX servers? I have 2 CAS servers and 4 MBX servers.

    Thanks,

    Jim

    Reply
  8. Hi again Rajith!

    It seems my issues stemmed from our 2003 env. that I migrated from a month ago, I removed the CN=Servers container from the old first administrative group due to public folder issues, and that seems to have solved this issue as well because when I created a new users just now everything went without a hitch!

    Thanks for a great blog and because you take time to answer comments :)

    /Jakob

    Reply
  9. Hi!

    Thanks for the reply, I have three servers, two MB (DAG) and one CAS/HUB.
    When I check if agent is enabled with EMS on each server it is listed as enabled, but I ran cmdlet to enable it anyways.

    Got the same error when creating a new user after that thou, the .xml has been placed on all three.

    Thanks!

    Reply
  10. Hi!

    I've used more or less the same code as you did, but I get an exception when creating a mailbox:

    Warning:
    The cmdlet extension agent with the index 5 has thrown an exception in OnComplete(). The exception is: Microsoft.Exchange.Provisioning.ProvisioningException: ScriptingAgent: Exception thrown while invoking scriptlet for OnComplete API: The operation couldn't be performed because object 'username' couldn't be found on 'dc2.domain.local'.. —> Microsoft.Exchange.Configuration.Tasks.ManagementObjectNotFoundException: The operation couldn't be performed because object 'hlinda' couldn't be found on 'dc2.domain.local'.

    The code:

    if($succeeded)
    {

    $mailbox = $provisioningHandler.UserSpecifiedParameters["Alias"]

    Set-User -City 'Stockholm' -CountryOrRegion 'Sweden' -Company 'Company Inc' -Identity $mailbox

    Set-Mailbox $mailbox -SingleItemRecoveryEnabled $true
    }

    If I do the commands manually they work.

    Oh, and thanks for an excellent blog!

    Reply
  11. I'm getting error on each command after I used exactly same code:

    WARNING: An unexpected error has occurred and a Watson dump is being generated: Object reference not set to an instance
    of an object.
    Object reference not set to an instance of an object.
    + CategoryInfo : NotSpecified: (:) [Get-CmdletExtensionAgent], NullReferenceException
    + FullyQualifiedErrorId : System.NullReferenceException,Microsoft.Exchange.Management.ProvisioningAgentTasks.GetCm
    dletExtensionAgent

    Reply
    • I got the same problem as you. I started from an empty SciptingAgentConfig.xml, then copy/pasted code from above. I then got that Watson error each time I ran a cmdlet, ANY cmdlet, not just New-Maibox. I also got the same Watson error if I copy/pasted the code from Pat Richard’s post.

      So I instead started from the ScriptingAgentConfig.xml.sample file, copy/pasted the FILE into ScriptingAgentconfig.xml (the FILE, not the contents!). I then deleted sections i did not need, and modified what I needed. No more Watson error!

      Pat

      Reply
  12. This is really handy. Looking forward to finishing our Exchange 2003 -> 2010 migration and putting stuff like this into use.

    I'm guessing that this needs to be done on each machine that you're running EMS from, right?

    Reply

Leave a Comment