FIM 2010 MA: Mailbox provisioning through Exchange Management Shell

 

The Exchange Server administrators usually keep separate mailbox databases to organize the users and their quotas.  In this particular scenario, the Exchange account provisioning on an appropriate database using FIM 2010 would require a mechanism for retrieving the list of databases and its properties before making a provisioning decision.

The solution that I opted for, involved defining a few additional rules in the Management Agent Extension. Particularly, in my case I already had a need a custom extension to meet some business requirements so this didn’t seem too much of an effort.

This solution relies on the Windows Remote Management and Remote Exchange Management Shell. Some reference material on these technologies can be found at Connect Remote Exchange Management Shell to an Exchange Server and Windows PowerShell SDK.

Exchange Management or any other PowerShell based management Cmdlets can be access through the PowerShell SDK.  Below is the a sample that I used for creating a PowerShell session is as below:

        private Collection<PSObject> RunScript(string command, 
string param, string paramValue)
        {
            Collection<PSObject> psResult = null;
            using (Runspace runspace = 
RunspaceFactory.CreateRunspace(this._connectionInfo))
            {
                using (PowerShell powershell = PowerShell.Create())
                {
                    powershell.AddCommand(command);
                    powershell.AddParameter(param, paramValue);
                    try
                    {
                        runspace.Open();
                        powershell.Runspace = runspace;
                        psResult = powershell.Invoke();
                    }
                    catch (Exception ex)
                    {

                WriteEventException(

                    new MetadirectoryServicesException(

                   "Exchange Remote Management Exception:" +

                   ex.ToString())

                    );

                    }
                    return psResult;
                }
            }
        }

The RunspaceFactory.CreateRunspace method requires a valid set of credentials and a URL for the PowerShell virtual directory on the target server.  This URL is typically http:// <servername>/PowerShell.  Before calling the RunScript method I had the following snippet in my helper class to instantiate the PSCredential and WSManConnectionInfo objects.

PSCredential credential = 
new PSCredential(this._user, this
._password); this._connectionInfo =
new WSManConnectionInfo(new Uri(this._serverUrl),
"http://schemas.microsoft.com/powershell/Microsoft.Exchange"
,
credential);
this._connectionInfo.AuthenticationMechanism =
AuthenticationMechanism.Default;

Additionally I used a few wrapper methods for sending specific commands through the remote shell;

Snippet for getting mailbox database statistics:
       public Dictionary<string, int> GetMailboxDatabaseStatistics()
        {
            Dictionary<string, int> mailboxProperties = 
new Dictionary<string, int
>();
            List<string> mailboxDBList = this.GetMailboxDatabases();
            int mailboxCount = 0;
            foreach (string mailbox in mailboxDBList)
            {
                mailboxCount = this.GetMailboxCount(mailbox);
                mailboxProperties.Add(mailbox, mailboxCount);
            }
            return mailboxProperties;
        }
Retrieve list of mailboxes
       private List<string> GetMailboxDatabases()
        {
            string command = "Get-MailboxDatabase";
            string param = "status";
            string paramValue = null;
            List<string> mailboxList = new List<string>();
            Collection<PSObject> result = 
this
.RunScript(command, param, paramValue);
            foreach (PSObject obj in result)
            {
                    mailboxList.Add(obj.Members["Name"].Value.ToString());
            }
            return mailboxList;
        }
Total number of mailboxes on a given database

        private int GetMailboxCount(string mailboxDatabase)

        {

            string command = "Get-MailboxStatistics";

            string param = "Database";

            string paramValue = mailboxDatabase;

            List<string> mailboxList = new List<string>();

            return this.RunScript(command, param, paramValue).Count;

        }

Fetching the right set of information using the above snippets and through Exchange Management Shell provides you every bit of information that you need on the current status of any given database.  Once you have a simple sorting/filter method written to choose a desired database,  the final step is to map the attributes flow to the Metaverse and then finally to the homeMDB attribute in the active directory.

Leave a Reply