none
How to build a .Net 4.5, C#, ASP.NET web site, to create/remove/modify Exchange 2010 mail accounts using Power Shell RRS feed

  • Question

  • I am trying to build a .Net 4.5, C#, ASP.NET web site, to create/remove/modify Exchange 2010 mail accounts using Power Shell.

    Akashb has a .NET 2.0 Exchange 2007 example (http://blogs.msdn.com/b/akashb/archive/2009/01/30/howto-using-powershell-in-asp-net-net-framework-2-0.aspx) that is very well done, but as Chuck Bigham pointed out, "Exchange 2010 uses Remote PowerShell" now.

    I unsuccessfully tried using "RunspaceConfiguration.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out error);

    The Exchange Team's posting at http://msexchangeteam.com/archive/2009/11/02/453016.aspx seems to be what's needed but is missing some key components and does not compile. I cannot find the WSManConnectionInfo namespace to reference.

    Can some please provide a complete working example of using Remote PowerShell to Exchange 2010.

    Chris Mangiapane, MCSD


    Chris
    Monday, August 22, 2011 8:02 PM

Answers

  • Here's a bare bones example in a console application. Just add a reference to system.management.automation.dll

    using System;
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;
    using System.Management.Automation.Remoting;
    using System.Collections.ObjectModel;
     
    namespace EMS_1
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Use Windows Authentication
                PSCredential creds = (PSCredential)null;
     
                WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
                    new Uri("http://cas1.uss.local/powershell"),
                    "http://schemas.microsoft.com/powershell/Microsoft.Exchange",
                    creds
                    );
     
                using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
                {
                    runspace.Open();
     
                    using (PowerShell powershell = PowerShell.Create())
                    {
                        powershell.AddCommand("Get-Mailbox");
                        powershell.AddParameter("ResultSize""Unlimited");
                        powershell.Runspace = runspace;
     
                        Collection<PSObject> results = powershell.Invoke();
                        foreach (PSObject result in results)
                        {
                            Console.WriteLine(result.Properties["DisplayName"].Value.ToString());
                        }
                    }
                }
            }
        }
    }

    Mike Pfeiffer | blog: mikepfeiffer.net | twitter: @mike_pfeiffer
    • Marked as answer by mangia Wednesday, August 24, 2011 6:16 PM
    Tuesday, August 23, 2011 3:50 PM

All replies

  • Here's a bare bones example in a console application. Just add a reference to system.management.automation.dll

    using System;
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;
    using System.Management.Automation.Remoting;
    using System.Collections.ObjectModel;
     
    namespace EMS_1
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Use Windows Authentication
                PSCredential creds = (PSCredential)null;
     
                WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
                    new Uri("http://cas1.uss.local/powershell"),
                    "http://schemas.microsoft.com/powershell/Microsoft.Exchange",
                    creds
                    );
     
                using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
                {
                    runspace.Open();
     
                    using (PowerShell powershell = PowerShell.Create())
                    {
                        powershell.AddCommand("Get-Mailbox");
                        powershell.AddParameter("ResultSize""Unlimited");
                        powershell.Runspace = runspace;
     
                        Collection<PSObject> results = powershell.Invoke();
                        foreach (PSObject result in results)
                        {
                            Console.WriteLine(result.Properties["DisplayName"].Value.ToString());
                        }
                    }
                }
            }
        }
    }

    Mike Pfeiffer | blog: mikepfeiffer.net | twitter: @mike_pfeiffer
    • Marked as answer by mangia Wednesday, August 24, 2011 6:16 PM
    Tuesday, August 23, 2011 3:50 PM
  • I have a rather large example I can send you. See my signature for my email address

    I use a common functions library, as I also manage Users, Groups, Contacts, etcetera, but I have stripped just the mailbox stuff out for the sample.

    This is my run script function:

      public static Collection<PSObject> RunScript(string strScript)
      {
        HttpContext.Current.Session["ScriptError"] = "";
        System.Uri serverUri = new Uri(String.Format("http://" + HttpContext.Current.Session["Server"].ToString() + "/powershell?serializationLevel=Full"));
        RunspaceConfiguration rc = RunspaceConfiguration.Create();
        WSManConnectionInfo wsManInfo = new WSManConnectionInfo(serverUri, SHELL_URI, (PSCredential)null);
        using (Runspace runSpace = RunspaceFactory.CreateRunspace(wsManInfo))
        {
          runSpace.Open();
          PowerShell posh = PowerShell.Create();
          posh.Runspace = runSpace;
          posh.AddScript(strScript);
          Collection<PSObject> results = posh.Invoke();
          if (posh.Streams.Error.Count > 0)
          {
            bool blTesting = false;
            string strType = HttpContext.Current.Session["Type"].ToString();
            if (HttpContext.Current.Session["Testing"] != null) 
            {
              blTesting = (bool)HttpContext.Current.Session["Testing"]; 
            }
            ErrorRecord err = posh.Streams.Error[0];
            if (err.CategoryInfo.Reason == "ManagementObjectNotFoundException")
            {
              HttpContext.Current.Session["ScriptError"] = "Management Object Not Found Exception Error " + err + " running command " + strScript;
              runSpace.Close();
              return null;
            }
            else if (err.Exception.Message.ToString().ToLower().Contains("is of type usermailbox.") && (strType.ToLower() == "mailbox"))
            {
              HttpContext.Current.Session["ScriptError"] = "Mailbox " + HttpContext.Current.Session["Display"].ToString() + " already exists.";
              runSpace.Close();
              return null;
            }
            else
            {
              HttpContext.Current.Session["ScriptError"] = "Error " + err + "<br />Running command " + strScript;
              fnWriteLog(HttpContext.Current.Session["ScriptError"].ToString(), "error", strType, blTesting);
              runSpace.Close();
              return null;
            }
          }
          runSpace.Close();
          runSpace.Dispose();
          posh.Dispose();
          posh = null;
          rc = null;
          if (results.Count != 0)
          {
    
    
    // You could show all results here. I choose not to
    
    //        foreach (PSObject resp in results)
    //        {
    //          System.Web.HttpContext.Current.Response.Write("Commamnd: " + resp.ToString() + "<br />");
    //        }
    //        return results[0];
            return results;
          }
          else
          {
            return null;
          }
        }
      }
    
    

    Karl


    My Blog: http://unlockpowershell.wordpress.com
    My Book: Windows PowerShell 2.0 Bible
    My E-mail: -join ("6B61726C6D69747363686B65406D742E6E6574"-split"(?<=\G.{2})",19|%{[char][int]"0x$_"})
    Wednesday, August 24, 2011 3:03 PM
  • Thank you very much Mike!  I was close but my implementation was using:
    Pipeline thisPipeline = thisRunspace.CreatePipeline();
    

    instead of a simple

    PowerShell powershell = PowerShell.Create();
    

    Your procedure is a clear and simple, and it works!

     

    Okay, so know I have one more question:  I am starting with a 'New-MailUser' cmdlet.  I run the code, the powershell.Invoke(); returns no error, but the email account is not created in Exchange 2010.  Do I need to create an AD user first?  Here an example of my command and parameters:

              powershell.AddCommand("New-MailUser");
              powershell.AddParameter("ExternalEmailAddress", "ChrisExchangeTest@someoutsidedomain.com");
              powershell.AddParameter("Name", "Chris");
              powershell.AddParameter("Password", ToSecureString("test"));
              powershell.AddParameter("UserPrincipalName", "ChrisExchangeTest@myexchangedomain.com");
              powershell.AddParameter("DisplayName", "Chris ExchangeTest");
              powershell.AddParameter("FirstName", "Chris");
              powershell.AddParameter("LastName", "ExchangeTest");
              powershell.AddParameter("ResetPasswordOnNextLogon", false);
              powershell.AddParameter("Alias", "Chris");
    
              powershell.Runspace = runspace;
    


    Please advise.




    Chris
    Wednesday, August 24, 2011 6:24 PM
  • Looking at your other thread it seems you probably figured this out already. If not, check the Streams property of the PowerShell object to see if any command errors were generated:

    if (powershell.Streams.Error.Count > 0)
    {
        foreach (ErrorRecord error in powershell.Streams.Error)
        {
            Console.WriteLine(error.ToString());
        }
    }

    That'll give you errors that are being generated by the cmdlet...like that user already exists, the password doesn't meet the complexity requirements, etc.


    Mike Pfeiffer | blog: mikepfeiffer.net | twitter: @mike_pfeiffer
    Thursday, August 25, 2011 3:20 AM
  • Hi,

    can anybody helps me getting a developer project w/ using exchange / powershell creating a website

    regards

    kaiman

    Friday, May 4, 2012 11:12 AM