OUTBOX: Introduction to Exchange Powershell Automation Part 2

  • Comments 4

Naturally the first case I had was how to create a mailbox using Powershell cmdlets from ASP.NET given that CDOEXM is no longer available.  From there we have had other bridges to cross as customers are upgrading 32-bit applications to work on Exchange 2007 (which is 64-bit) and replacing old CDOEXM code with Exchange Management Shell cmdlet automation.  Through these early cases I identified a couple common themes and created some sample code that I thought might be helpful to share here…

 

Exchange Cmdlets and Impersonation

Much like we saw with CDOEXM, currently we don’t recommend or support using Exchange Powershell cmdlets with impersonation.  In the case of creating a mailbox in an ASP.NET application we would recommend that you use COM+ or .NET Remoting to host your Powershell code, have that code run as a service account with permissions to execute the Powershell cmdlets and then implement authorization logic to evaluate if the caller has permission to execute the code.  Click here for more information.

 

Exchange Management Shell Snap-in and 32-bit Applications

This typically isn’t a problem when writing an application in VB.NET or C# because the projects default to 64-bit on 64-bit machines but if you are trying to load the Exchange Management Shell Snap-in in a 32-bit instance of Powershell you will get the following error…

 

"No Windows PowerShell Snap-ins are available for version 1"

 

…This is because Exchange 2007 is a 64-bit application and therefore the snap-in is also 64-bit and cannot be loaded into a 32-bit instance of the shell.  Click here for more information.

 

C# Sample – New-Mailbox

Here is sample of a function which takes input to create a new mailbox using the New-Mailbox cmdlet…

 

public static void CreateUserMailbox(string domain, string ou,

    string database, string alias, string name,

    string displayName, SecureString password)

{

    string upn = string.Format("{0}@{1}", alias, domain);

 

    ICollection<PSObject> results;

 

    // Create a runspace. We can't use the RunspaceInvoke class this time

    // because we need to get at the underlying runspace to explicitly

    // add the commands.

    RunspaceConfiguration rc = RunspaceConfiguration.Create();

    PSSnapInException snapEx = null;

    PSSnapInInfo info = rc.AddPSSnapIn(

        "Microsoft.Exchange.Management.PowerShell.Admin",

        out snapEx);

    Runspace myRunSpace = RunspaceFactory.CreateRunspace(rc);

    myRunSpace.Open();

 

    // Create a pipeline...

    Pipeline pipeLine = myRunSpace.CreatePipeline();

 

    using (pipeLine)

    {

        // Create a command object so we can set some parameters

        // for this command.

        Command newMbx = new Command("new-mailbox");

        newMbx.Parameters.Add("alias", alias);

        newMbx.Parameters.Add("database", database);

        newMbx.Parameters.Add("password", password);

        newMbx.Parameters.Add("Name", name);

        newMbx.Parameters.Add("DisplayName", displayName);

        newMbx.Parameters.Add("UserPrincipalName", upn);

        newMbx.Parameters.Add("OrganizationalUnit", ou);

 

        // Add the command we've constructed

        pipeLine.Commands.Add(newMbx);

 

        // Execute the pipeline and save the objects returned.

        results = pipeLine.Invoke();

 

        // Print out any errors in the pipeline execution

        // NOTE: These error are NOT thrown as exceptions!

        // Be sure to check this to ensure that no errors

        // happened while executing the command.

        if (pipeLine.Error != null && pipeLine.Error.Count > 0)

        {

            Trace.WriteLine("ERROR: There were pipeline errors...\n");

            foreach (object item in pipeLine.Error.ReadToEnd())

            {

                Trace.WriteLine("Error: " + item.ToString() + "\n");

            }

        }

 

        // Print out the results of the pipeline execution

        if (results != null && results.Count > 0)

        {

Trace.WriteLine("MAILBOXES CREATED: Created the following      mailboxes...\n");

            foreach (PSObject ps in results)

            {

                if (ps.Members["UserPrincipalName"].Value != null)

                {

                    Trace.WriteLine("UserPrincipalName: "

                        + ps.Members["UserPrincipalName"].Value + "\n");

                }

            }

        }

    }

 

    pipeLine = null;

    myRunSpace.Close();

    myRunSpace = null;

}

 

Notice that I use a Pipeline instead of RunspaceInvoke (like Vivek did).  RunspaceInvoke works fine in a lot of cases but the advantage I found with the Pipeline is that it is quite easy to add non-string parameters like the SecureString object to the cmdlet call.  Also, note that while the Invoke method returns a result array of PSObjects there is also an Error property which has an array of exceptions.  This error information is generally going to be validation type errors, for instance in the case of New-Mailbox I might get an error that the mailbox already in this property but I would get an exception if I misspelled New-Mailbox.

 

Sample Code on the Web

Vivek Sharma: Sample Code: Calling Exchange cmdlets from .NET Code

http://www.viveksharma.com/techlog/2006/07/27/sample-code-calling-exchange-cmdlets-from-net-code

 

Glen Scales: Quick Create Mailbox Powershell Form for Exchange 2007

http://gsexdev.blogspot.com/2006/12/quick-create-mailbox-powershell-form.html

 

Glen Scales: Scripting Exchange Web Services (2007) with VBS and Powershell

http://gsexdev.blogspot.com/2006/12/scripting-exchange-web-services-2007.html

 

Glen Scales: Exchange SMTP Log file DNS Test tool Powershell script

http://gsexdev.blogspot.com/2006/12/exchange-smtp-log-file-dns-test-tool.html

 

…this isn’t necessarily related but I had to include it because it is just so cool…

Glen Scales: Geolocating Exchange Message Tracking with Powershell (Exchange 2000/2003) (Seeing what countries your messages/Spam are coming from)

http://gsexdev.blogspot.com/2006/11/geolocationing-exchange-message.html

  • What is the reasoning behind explicitly blocking impersonation calls to powershell cmdlets?

  • Trying to call Powershell from .net ? Following are few good articles to read, from my colleague Matt

  • Mentre stavo per realizzare l'ennesima applicazione web che interagiva con Exchange attraverso la libreria

  • I've put together a list of articles which cover common questions on PowerShell automation. These links

Page 1 of 1 (4 items)