Cmdlet Extension Agents Part 1: Automatic archive creation

Cmdlet Extension Agents Part 2: Postconfiguring Mailboxes

An Exchange fellow inquired about the possibility to automatically enable personal archives when creating mailboxes with the added requirement to create those personal archives in a specific mailbox database, depending on the location of the mailbox. Dedicated mailbox databases were used for personal archives. Simply said, the idea was that mailboxes located in database MDB1 should get a personal archive in mailbox database ADB1, MDB2 in ADB2, etc.

Your first thought could be creating a script to automatically provision those personal archives in the proper database depending on the mailbox database. But alas, when using Exchange 2010’s automatic mailbox provisioning system you never know upfront what mailbox database will be appointed.

That leads us to Exchange 2010’s Cmdlet Extension Agents, more specific the Scripting Agent. I won’t go into much detail now on those Agents, but look at them as a way to extend cmdlets by adding pre- and post-jobs, additional constraints, reporting or override parameters.

Now, when you haven’t already done so, first exclude the mailbox databases containing personal archives from automatic provisioning. If you have a dedicated server for hosting personal archives, use the IsExcludedFromProvisioning with the Set-MailboxServer cmdlet; to exclude a mailbox database use IsExcludedFromProvisioning with the Set-MailboxDatabase, e.g.

Set-MailboxDatabase <Archive Database ID> –IsExcludedFromProvisioning $true

image

I’ll first show you how the scripted version could work. We’ll start by creating some mailboxes. We don’t require anything fancy, so this will do:

$pwd= ConvertTo-SecureString -AsPlainText “Welcome1 -Force
1..10 | ForEach { New-Mailbox “User$_ -Password $pwd -UserPrincipalName user$_@<domain> }

A quick overview of the result shows the mailboxes are created in a round robin fashion:

image

What you could do now is enabling the archive on ADB1 for MDB1 and ADB2 for MDB2 mailboxes, e.g.

Get-Mailbox –Database MDB1 | Enable-Mailbox –Archive -ArchiveDatabase ADB1
Get-Mailbox –Database MDB2 | Enable-Mailbox –Archive -ArchiveDatabase ADB2

image

This is what we wanted. As you probably understand, the main disadvantage now is that this only works for the current mailbox population. Administrators should appoint the proper mailbox database for personal archives when creating new mailboxes. Can the Scripting Agent overcome this problem?

Let’s have a look on how to configure the Scripting Agent. Open up Notepad and create a file \bin\CmdletExtensionAgents\ScriptingAgentConfig.xml located in Env:ExchangeInstallPath, e.g. C:\Program Files\Microsoft\Exchange Server\V14\Bin\CmdletExtensionAgents, using the following contents:

<?xml version="1.0" encoding="utf-8" ?>
  <Configuration version="1.0">
  <Feature Name="MailboxProvisioning" Cmdlets="New-Mailbox">
  <ApiCall Name="OnComplete">
  If($succeeded) {
    $Name= $provisioningHandler.UserSpecifiedParameters["Name"]
    If ((Get-Mailbox $Name).ArchiveDatabase -eq $null) {
      $MailboxDatabase= (Get-Mailbox $Name).Database
      $ArchiveDatabase= "A"+ ( $MailboxDatabase.Name).Substring( 1)
      Enable-Mailbox $Name -Archive -ArchiveDatabase $ArchiveDatabase
    }
  }
  </ApiCall>
  </Feature>
  </Configuration>

A small explanation might be appropriate:

  • The Cmdlets specified in this feature extension dictates which cmdlets will be extended;
  • OnComplete dictates that our script will fire when the cmdlet has finished;
  • We check for OnComplete parameter $succeeded, only enabling archives when the preceding cmdlet was successful;
  • $provisioningHandler.UserSpecifiedParameters contains user provided parameters passed to the cmdlet. So, $provisioningHandler.UserSpecifiedParameters[“Name”] will return the value of -Name;
  • We’ll check if the mailbox already has a personal archive configured; if not, we can proceed;
  • Next, we’ll get the current MailboxDatabase. Then we’ll map that to our personal archive naming scheme by stripping the first character and prefix it with “A”;
  • Finally, we can execute the cmdlet to enable the personal archive of the mailbox on the database specified.

Now, before we test our scripting agent, we need to distribute the XML file on all of our Exchange servers. The reason for this is that you don’t know which Exchange server an administrator will connect to or which server will execute the cmdlet. The location to copy the XML file to is the local CmdletExtensionAgents folder.

Now there’s one more thing we need to do, which is enabling the Scripting Agent. The Scripting Agent is disabled by default. Use the Enable-CmdletExtensionAgent cmdlet to enable it, e.g.:

Enable-CmdletExtensionAgent “Scripting Agent”

Now, when we use the same cmdlet we used before to create those mailboxes, we get the following result:

image

As you can see, archive databases are now nicely aligned with the automatically assigned mailbox databases.

A small note for those wishing to experiment with the Scripting Agent. Alternatively to OnComplete, you can also try defining the personal archive parameters using the ApiCall ProvisionDefaultProperties. This ApiCall can be used to define default attributes when creating a mailbox. However, this leads to a catch 22 situation and has to do with the Mailbox Resources Management Agent.

By default the Mailbox Resources Management Agent has higher priority (2) than the Scripting Agent (6). This means it will override any settings made in our Scripting Agent.

image

The Mailbox Resources Management Agent is responsible for the automatic mailbox distribution when you don’t specify a mailbox database when creating a mailbox. But it is also responsible for assigning a mailbox database for the personal archive when you don’t specify the ArchiveDatabase parameter.

So, unless we want to add all the automatic mailbox distribution logic to our script, we can’t use the ProvisionDefaultProperties ApiCall properly, because if we want to use that, we need to assign the Scripting Agent a higher priority than the Mailbox Resources Management Agent, but at that point we have no database value so we can’t determine the proper archive database.

If you’re interested in playing with this, check out the ScriptingAgentConfig.xml.sample file which is located in the CmdletExtensionAgents as well. If you’re looking for more information on Cmdlet Extension Agents, check here; information on the Scripting Agent can be found here. More information on the automatic mailbox distribution process here.

21 thoughts on “Cmdlet Extension Agents Part 1: Automatic archive creation

  1. Glad to see someone else is also writing about cmdlet extension agents. I’ve gotten a lot of feedback since writing my article, and have long thought this is a WAY under-utilized feature that could use more exposure. Nice article.

    • Thanks Brian. I agree error and type checking could be added, but that would defeat the purpose of this post. Also, since Name is a String, you can’t feed it multiple values; Wildcards will be parsed as text. Invalid values will be caught by the cmdlet itself since we only will continue after successfully executing that cmdlet. Perhaps you can share your thoughts here?

  2. Consider this scenario:

    Create a Mailbox with “-Name John.Doe”
    Create a Mailbox with “-Name John”

    In your extension, what does “Get-Mailbox John” return?

    • Why’d you think “Get-Mailbox John” would return John.Doe’s mailbox? For your peace of mind:

      New-Mailbox John -Password $pwd -UserPrincipalName john@fourteen.com
      New-Mailbox John.Doe -Password $pwd -UserPrincipalName john.doe@fourteen.com
      Get-Mailbox | select Name,Database,ArchiveDatabase

      Name Database ArchiveDatabase
      —- ——– —————
      Administrator MDB1
      DiscoverySearchMailbox {D919BA05-46A… MDB1
      John MDB1 ADB1
      John.Doe MDB2 ADB2

    • Then I’d have to explicitly use -ANR for Get-Mailbox, now it maps “Name” to Identity. Reason for this is that Identity is a positional parameter and ANR a named parameter; since we didn’t specify ANR, the first argument is assigned to Identity.

  3. Pingback: Using the Scripting Agent to automate some basic “housekeeping” tasks - Exchange 2010 - Pro-Exchange,Lync & Office 365

  4. Pingback: Analyzing what’s in the Exchange 2010 SP2 RU2 update | Thoughtsofanidlemind's Blog

  5. Hi thanks for your post
    I try to enable the same extension with “enable-mailbox” as follow
    but I always has the following error
    Cannot bind parameter ‘Identity’. Cannot convert the “user.name” value of type
    “Microsoft.Exchange.Configuration.Tasks.UserIdParameter” to type
    “Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter”.. —>

    any idea ?

    If($succeeded)
    {
    $Name= $provisioningHandler.UserSpecifiedParameters[“Identity”]
    If ((Get-Mailbox $Name).archivedatabase -eq $null)
    {
    $MailboxDatabase= (Get-Mailbox $Name).database
    if($MailboxDatabase -eq “NOM_SYS”){$ArchiveDatabase= “ARCH_MGMT”}
    elseif($MailboxDatabase -eq “NOM_SUPPORT_01″){$ArchiveDatabase= “ARCH_MGMT”}
    elseif($MailboxDatabase -eq “NOM_MGMT_01″){$ArchiveDatabase= “ARCH_MGMT”}
    elseif($MailboxDatabase -eq “NOM_MGMT2_01″){$ArchiveDatabase= “ARCH_MGMT”}
    else{$ArchiveDatabase= ( $MailboxDatabase.Name)}
    Enable-Mailbox $Name -Archive -ArchiveDatabase $ArchiveDatabase
    }
    }

    • Identity isn’t a parameter to be used with New-Mailbox; Identity is used in Get/Set by ANR (ambigious name resolution) to look up the provided ‘identity’ value using fields like GUI,DN,DisplayName,UPN,alias, etc.
      So, what you need to use is the provided Name parameter, e.g.
      $Name= $provisioningHandler.UserSpecifiedParameters[“Name”]

      I overlooked you are using it for Enable-Mailbox, not New-Mailbox. However, I have a gut feeling it has to do with the reason provided in the earlier reply; could you provide the XML?

  6. Pingback: Preconfiguring Mailboxes – Cmdlet Extension Agents Part 2 | EighTwOne (821)

  7. Pingback: Preconfiguring Mailboxes – Cmdlet Extension Agents Part 2 | EighTwOne (821)

  8. Pingback: Cmdlet Extension Agents Part 2: Postconfiguring Mailboxes | EighTwOne (821)

  9. Pingback: The UC Architects » Episode 4 Exchange: Catching The Wave (15)

  10. Pingback: Set Default Calendar permissions for all new Users to reviewer

  11. Pingback: Exchange 2010 Scripting Agent – flaphead.com

  12. Pingback: Can’t Create Mailboxes in Remote Sites | EighTwOne (821)

  13. Michel, I see issues using Cmdlet Extension Agents, particularly in a large Exchange environment with multiple sites. I have Exchange 2013 in 2 sites and with replication taking a minimum of 15 minutes, we see the agent not finding the mailbox because it is being invoked in another AD site. Have you see this issue before? I was trying to find a way to insert the OriginatingServer into the cmdlet so we can then add the domaincontroller parameter.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s