Access Exchange Online by PowerShell in C#

For exchange online management, the most convenient and powerful approach is Exchange Online PowerShell Cmdlet. Before calling each management cmdlet, we need establish a remote session firstly and Connect to Exchange Online PowerShell is a good start for this.


In the meantime, probably you would like to access exchange online from C#, such as a desktop application to provide management flexibility. This blog is regarding to this scenario step by step.


Step 1

Firstly, we need construct a PSCredential object for user and secured password. connectionUril is same to all the office 365 tenant, and will be used later to establish the remote session.

string connectionUri = ""; string loginPassword = "thepassword"; SecureString secpassword = new SecureString(); foreach (char c in loginPassword) { secpassword.AppendChar(c); } PSCredential credential = new PSCredential("", secpassword);


Step 2

Create and open the runspace which is the container of the powershell session. the remote session will be established by cmdlet New-PSSession. We need check the error and result to make sure everything is going fine.

Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(); PowerShell powershell = PowerShell.Create(); PSCommand command = new PSCommand(); command.AddCommand("New-PSSession"); command.AddParameter("ConfigurationName", "Microsoft.Exchange"); command.AddParameter("ConnectionUri", new Uri(connectionUri)); command.AddParameter("Credential", credential); command.AddParameter("Authentication", "Basic"); powershell.Commands = command; runspace.Open(); powershell.Runspace = runspace; Collection<System.Management.Automation.PSObject> result = powershell.Invoke(); if (powershell.Streams.Error.Count > 0 || result.Count != 1) { throw new Exception("Fail to establish the connection"); }


Step 3

Let's try to retrieve all the mailboxes by cmdlet Get-Mailbox. As we need run the command in the remote session just established, we need Invoke-Command as it provides the ability to run the command in a specific session. In this example, we will get all the mailbox and select the target based on DisplayName.

powershell = PowerShell.Create(); command = new PSCommand(); command.AddCommand("Invoke-Command"); command.AddParameter("ScriptBlock", System.Management.Automation.ScriptBlock.Create("Get-Mailbox")); command.AddParameter("Session", result[0]); powershell.Commands = command; powershell.Runspace = runspace; var mailBoxes = powershell.Invoke(); var targetBox = mailBoxes.Where(i => (string)i.Properties["DisplayName"].Value == "Jacky Wu").FirstOrDefault(); var identity = targetBox.Properties["Identity"].Value;


Step 4

Based on the identity retrieved in last step, let's call Set-Mailbox to set the corresponding IssueWarningQuota.

powershell = PowerShell.Create(); command = new PSCommand(); command.AddCommand("Invoke-Command"); command.AddParameter("ScriptBlock", System.Management.Automation.ScriptBlock.Create("Set-Mailbox -Identity " + identity + " -IssueWarningQuota 16GB")); command.AddParameter("Session", result[0]); powershell.Commands = command; powershell.Runspace = runspace; powershell.Invoke();


Step 5

Lastly, we need dispose the runspace to release the connection. By default, the maximum number of the concurrent remote connections is 3. Certainly, it is a good idea to wrap the above code in a try-finally block to make it. By the way, notice that I just execute Get-MailBox and Set-MailBox in two separate invokes to demonstrate get and set usage, feel free to compose more complicated command combination such as pipeline in a single invoke-command.


Basically, access exchange online cmdlet from C# is not as straightforward as Powershell script directly, may be more suitable for lightweight management. The above code is confirmed to work in exchange on-premises as well, while need some code revise such as connectionUri and Authentication (set to default). Hope this is helpful.